Replace vector.h with vector-wrapper.h
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / replacement.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // INTERNAL INCLUDES
19 #include <dali-toolkit/internal/builder/replacement.h>
20 #include <dali-toolkit/internal/builder/builder-impl.h>
21 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
22
23 namespace Dali
24 {
25
26 namespace Toolkit
27 {
28
29 namespace Internal
30 {
31
32 namespace  // anon
33 {
34
35 Property::Value* FindReplacement( const std::string &str, const Property::Map& overrideMap, const Property::Map& defaultMap )
36 {
37   Property::Value* ret  = overrideMap.Find( str );
38
39   if ( !ret )
40   {
41     ret = defaultMap.Find( str );
42
43     // @ todo
44     // try localized text ie dgettext. Look for colon  {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
45   }
46
47   return ret;
48 }
49
50 std::size_t FirstUnescapedChar(const std::string &initialValue, const std::size_t& startPos, const char c)
51 {
52   std::size_t pos = initialValue.find( c, startPos );
53
54   if(pos > 0)
55   {
56     while( pos != std::string::npos )
57     {
58       if( '\\' == initialValue.at( pos-1 ) )
59       {
60         pos = initialValue.find( c, pos );
61       }
62       else
63       {
64         break;
65       }
66     }
67   }
68
69   return pos;
70 }
71
72 bool GetSubstitutionPosition( const std::string &initialValue, std::size_t &startPos, std::size_t &size )
73 {
74   std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
75
76   if( std::string::npos == pos )
77   {
78     startPos = std::string::npos;
79     return false;
80   }
81   else
82   {
83     startPos = pos + 1;
84   }
85
86   pos = FirstUnescapedChar(initialValue, startPos, '}');
87
88   if( std::string::npos == pos )
89   {
90     size = std::string::npos;
91     return false;
92   }
93   else
94   {
95     size = pos - startPos;
96   }
97
98   return true;
99 }
100
101 bool ResolvePartialReplacement( const std::string &initialValue, Property::Value &out,
102                                 const Property::Map& overrideMap, const Property::Map& defaultMap )
103 {
104
105   if( initialValue.size() >= 2 )
106   {
107     // eg '{"constants": { "IMAGE_DIR": "/share/images" },
108     //      ...
109     //        "filename":"{IMAGE_DIR}/theme/header.png",
110     //
111     std::size_t startPos = 0;
112     std::size_t size     = std::string::npos;
113
114     if( !GetSubstitutionPosition( initialValue, startPos, size ) )
115     {
116       out = initialValue;
117       return true;
118     }
119     else
120     {
121       const std::string str( initialValue.substr( startPos, size ) );
122
123       Property::Value* value = FindReplacement( str, overrideMap, defaultMap );
124
125       if( !value )
126       {
127         DALI_SCRIPT_WARNING( "Cannot find replacement for '%s'\n", str.c_str() );
128       }
129       else
130       {
131         if( Property::STRING != value->GetType() )
132         {
133           DALI_SCRIPT_WARNING( "Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
134                                PropertyTypes::GetName( out.GetType() ), initialValue.c_str() );
135         }
136         else
137         {
138           std::string newString = \
139             initialValue.substr(0, startPos - 1) +
140             value->Get< std::string >() +
141             initialValue.substr( startPos + size + 1 );
142
143           return ResolvePartialReplacement( newString, out, overrideMap,  defaultMap );
144         }
145       }
146     }
147   }
148
149   // if we get here we failed
150   return false;
151 }
152
153 } // namespace anon
154
155
156 Replacement::Replacement( const Property::Map& overrideMap, const Property::Map& defaultMap )
157   : mOverrideMap( &overrideMap ), mDefaultMap( &defaultMap )
158 {
159
160 }
161
162 namespace
163 {
164 Property::Map noMap;
165 }
166
167 Replacement::Replacement( const Property::Map& defaultMap )
168   : mOverrideMap( &noMap ), mDefaultMap( &defaultMap )
169 {
170
171 }
172
173 Replacement::Replacement(  )
174   : mOverrideMap( &noMap ), mDefaultMap( &noMap )
175 {
176
177 }
178
179 OptionalString Replacement::HasFullReplacement( const TreeNode & node ) const
180 {
181   OptionalString ret;
182
183   if( node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()) )
184   {
185     OptionalString v = ::IsString( node );
186     if( v )
187     {
188       const std::string& initialValue = *v;
189       if( (initialValue[ 0 ] == '{') && (initialValue[ initialValue.size() -1 ] == '}') )
190       {
191         ret = initialValue.substr( 1, initialValue.size() - 2 );
192       }
193     }
194   }
195   return ret;
196 }
197
198 Property::Value Replacement::GetFullReplacement( const std::string& replacementString ) const
199 {
200   Property::Value out;
201   DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
202   DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
203
204   Property::Value* value = FindReplacement( replacementString, *mOverrideMap, *mDefaultMap );
205
206   if( !value )
207   {
208     DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
209   }
210   else
211   {
212     out = *value;
213 #if defined(DEBUG_ENABLED)
214     DALI_SCRIPT_VERBOSE("  Full replacement for '%s' => to Type '%s'\n",
215                         replacementString.c_str(),
216                         PropertyTypes::GetName( out.GetType()) );
217 #endif
218   }
219
220   return out;
221 }
222
223 OptionalBoolean Replacement::IsBoolean( const TreeNode & node ) const
224 {
225   OptionalBoolean ret;
226   if( OptionalString replace = HasFullReplacement( node ) )
227   {
228     Property::Value value = GetFullReplacement( *replace );
229     if( Property::BOOLEAN == value.GetType() )
230     {
231       ret = value.Get<bool>();
232     }
233   }
234   else
235   {
236     ret = ::IsBoolean( node );
237   }
238   return ret;
239 }
240
241 OptionalBoolean Replacement::IsBoolean( OptionalChild child ) const
242 {
243   if( child )
244   {
245     return IsBoolean( *child );
246   }
247   else
248   {
249     return OptionalBoolean();
250   }
251 }
252
253 OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
254 {
255   OptionalFloat ret;
256   if( OptionalString replace = HasFullReplacement( node ) )
257   {
258     Property::Value value = GetFullReplacement( *replace );
259     if( Property::FLOAT == value.GetType() )
260     {
261       ret = value.Get<float>();
262     }
263   }
264   else
265   {
266     ret = ::IsFloat( node );
267   }
268   return ret;
269 }
270
271 OptionalString Replacement::IsString( const TreeNode& node ) const
272 {
273   OptionalString ret;
274
275   DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
276   DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
277
278   if( node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()) )
279   {
280     if( OptionalString v = ::IsString( node ) )
281     {
282       Property::Value value;
283       if( ResolvePartialReplacement( *v, value, *mOverrideMap, *mDefaultMap ) )
284       {
285         if( Property::STRING == value.GetType() )
286         {
287           ret = value.Get<std::string>();
288 #if defined(DEBUG_ENABLED)
289           DALI_SCRIPT_VERBOSE("  Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
290 #endif
291         }
292       }
293       else
294       {
295         if( Property::STRING == value.GetType() )
296         {
297           ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
298         }
299       }
300     }
301   }
302   else
303   {
304     ret = ::IsString( node );
305   }
306   return ret;
307 }
308
309 OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
310 {
311   OptionalInteger ret;
312   if( OptionalString replace = HasFullReplacement( node ) )
313   {
314     Property::Value value = GetFullReplacement( *replace );
315     if( Property::INTEGER == value.GetType() )
316     {
317       ret = value.Get<int>();
318     }
319   }
320   else
321   {
322     ret = ::IsInteger( node );
323   }
324   return ret;
325 }
326
327 OptionalUnsignedInt Replacement::IsUnsignedInteger( const TreeNode & node ) const
328 {
329   OptionalUnsignedInt ret;
330   if( OptionalString replace = HasFullReplacement( node ) )
331   {
332     Property::Value value = GetFullReplacement( *replace );
333     if( Property::UNSIGNED_INTEGER == value.GetType() )
334     {
335       ret = value.Get<unsigned int>();
336     }
337   }
338   else
339   {
340     if ( OptionalInteger i = ::IsInteger( node ) )
341     {
342       ret = OptionalUnsignedInt(static_cast<unsigned int>(*i) );
343     }
344   }
345   return ret;
346 }
347
348 OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
349 {
350   OptionalVector2 ret;
351   if( OptionalString replace = HasFullReplacement( node ) )
352   {
353     Property::Value value = GetFullReplacement( *replace );
354     if( Property::VECTOR2 == value.GetType() )
355     {
356       ret = value.Get<Vector2>();
357     }
358   }
359   else
360   {
361     ret = ::IsVector2( node );
362   }
363   return ret;
364 }
365
366 OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
367 {
368   OptionalVector3 ret;
369   if( OptionalString replace = HasFullReplacement( node ) )
370   {
371     Property::Value value = GetFullReplacement( *replace );
372     if( Property::VECTOR3 == value.GetType() )
373     {
374       ret = value.Get<Vector3>();
375     }
376   }
377   else
378   {
379     ret = ::IsVector3( node );
380   }
381   return ret;
382 }
383
384 OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
385 {
386   OptionalVector4 ret;
387   if( OptionalString replace = HasFullReplacement( node ) )
388   {
389     Property::Value value = GetFullReplacement( *replace );
390     if( Property::VECTOR4 == value.GetType() )
391     {
392       ret = value.Get<Vector4>();
393     }
394   }
395   else
396   {
397     ret = ::IsVector4( node );
398   }
399   return ret;
400 }
401
402 OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
403 {
404   OptionalMatrix ret;
405   if( OptionalString replace = HasFullReplacement( node ) )
406   {
407     Property::Value value = GetFullReplacement( *replace );
408     if( Property::MATRIX == value.GetType() )
409     {
410       ret = value.Get<Matrix>();
411     }
412   }
413   else
414   {
415     ret = ::IsMatrix( node );
416   }
417   return ret;
418 }
419
420 OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
421 {
422   OptionalMatrix3 ret;
423   if( OptionalString replace = HasFullReplacement( node ) )
424   {
425     Property::Value value = GetFullReplacement( *replace );
426     if( Property::MATRIX3 == value.GetType() )
427     {
428       ret = value.Get<Matrix3>();
429     }
430   }
431   else
432   {
433     ret = ::IsMatrix3( node );
434   }
435   return ret;
436 }
437
438 OptionalRect Replacement::IsRect( const TreeNode & node ) const
439 {
440   OptionalRect ret;
441   if( OptionalString replace = HasFullReplacement( node ) )
442   {
443     Property::Value value = GetFullReplacement( *replace );
444     if( Property::RECTANGLE == value.GetType() )
445     {
446       ret = value.Get<Rect<int> >();
447     }
448   }
449   else
450   {
451     ret = ::IsRect( node );
452   }
453   return ret;
454 }
455
456
457
458 OptionalFloat Replacement::IsFloat( OptionalChild child ) const
459 {
460   if( child )
461   {
462     return IsFloat( *child );
463   }
464   else
465   {
466     return OptionalFloat();
467   }
468 }
469
470
471 OptionalString Replacement::IsString( OptionalChild child ) const
472 {
473   if( child )
474   {
475     return IsString( *child );
476   }
477   else
478   {
479     return OptionalString();
480   }
481 }
482
483 OptionalInteger Replacement::IsInteger( OptionalChild child ) const
484 {
485   if( child )
486   {
487     return IsInteger( *child );
488   }
489   else
490   {
491     return OptionalInteger();
492   }
493 }
494
495 OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
496 {
497   if( child )
498   {
499     return IsVector2( *child );
500   }
501   else
502   {
503     return OptionalVector2();
504   }
505 }
506
507 OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
508 {
509   if( child )
510   {
511     return IsVector3( *child );
512   }
513   else
514   {
515     return OptionalVector3();
516   }
517 }
518
519 OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
520 {
521   if( child )
522   {
523     return IsVector4( *child );
524   }
525   else
526   {
527     return OptionalVector4();
528   }
529 }
530
531 OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
532 {
533   if( child )
534   {
535     return IsMatrix( *child );
536   }
537   else
538   {
539     return OptionalMatrix();
540   }
541 }
542
543 OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
544 {
545   if( child )
546   {
547     return IsMatrix3( *child );
548   }
549   else
550   {
551     return OptionalMatrix3();
552   }
553 }
554
555 OptionalRect Replacement::IsRect( OptionalChild child ) const
556 {
557   if( child )
558   {
559     return IsRect( *child );
560   }
561   else
562   {
563     return OptionalRect();
564   }
565 }
566
567 bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
568 {
569   bool ret = false;
570
571   if( child )
572   {
573     if( OptionalString replace = HasFullReplacement( *child ) )
574     {
575       out = GetFullReplacement( *replace );
576       if( Property::MAP == out.GetType() )
577       {
578         ret = true;
579       }
580     }
581   }
582
583   return ret;
584 }
585
586 bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
587 {
588   bool ret = false;
589
590   if( child )
591   {
592     if( OptionalString replace = HasFullReplacement( *child ) )
593     {
594       out = GetFullReplacement( *replace );
595       if( Property::ARRAY == out.GetType() )
596       {
597         ret = true;
598       }
599     }
600   }
601
602   return ret;
603 }
604
605 } // namespace Internal
606
607 } // namespace Toolkit
608
609 } // namespace Dali
610