2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include <dali-toolkit/internal/builder/replacement.h>
19 #include <dali-toolkit/internal/builder/builder-impl.h>
20 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
34 PropertyValueMap::const_iterator FindReplacement( const std::string &str,
35 const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
37 PropertyValueMap::const_iterator ret = defaultMap.end();
39 PropertyValueMap::const_iterator iter = overrideMap.find( str );
41 if( iter != overrideMap.end() )
47 PropertyValueMap::const_iterator iter = defaultMap.find( str );
49 if( iter != defaultMap.end() )
56 // try localized text ie dgettext. Look for colon {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
64 std::size_t FirstUnescapedChar(const std::string &initialValue, const std::size_t& startPos, const char c)
66 std::size_t pos = initialValue.find( c, startPos );
70 while( pos != std::string::npos )
72 if( '\\' == initialValue.at( pos-1 ) )
74 pos = initialValue.find( c, pos );
86 bool GetSubstitutionPosition( const std::string &initialValue, std::size_t &startPos, std::size_t &size )
88 std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
90 if( std::string::npos == pos )
92 startPos = std::string::npos;
100 pos = FirstUnescapedChar(initialValue, startPos, '}');
102 if( std::string::npos == pos )
104 size = std::string::npos;
109 size = pos - startPos;
115 bool ResolvePartialReplacement( const std::string &initialValue, Property::Value &out,
116 const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
119 if( initialValue.size() >= 2 )
121 // eg '{"constants": { "IMAGE_DIR": "/share/images" },
123 // "filename":"{IMAGE_DIR}/theme/header.png",
125 std::size_t startPos = 0;
126 std::size_t size = std::string::npos;
128 if( !GetSubstitutionPosition( initialValue, startPos, size ) )
135 const std::string str( initialValue.substr( startPos, size ) );
137 PropertyValueMap::const_iterator iter = FindReplacement( str, overrideMap, defaultMap );
139 if( iter == defaultMap.end() )
141 DALI_SCRIPT_WARNING( "Cannot find replacement for '%s'\n", str.c_str() );
145 if( Property::STRING != (*iter).second.GetType() )
147 DALI_SCRIPT_WARNING( "Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
148 PropertyTypes::GetName( out.GetType() ), initialValue.c_str() );
152 std::string newString = \
153 initialValue.substr(0, startPos - 1) +
154 (*iter).second.Get<std::string>() +
155 initialValue.substr( startPos + size + 1 );
157 return ResolvePartialReplacement( newString, out, overrideMap, defaultMap );
163 // if we get here we failed
170 Replacement::Replacement( const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
171 : mOverrideMap( &overrideMap ), mDefaultMap( &defaultMap )
178 PropertyValueMap noMap;
181 Replacement::Replacement( const PropertyValueMap& defaultMap )
182 : mOverrideMap( &noMap ), mDefaultMap( &defaultMap )
187 Replacement::Replacement( )
188 : mOverrideMap( &noMap ), mDefaultMap( &noMap )
193 OptionalString Replacement::HasFullReplacement( const TreeNode & node ) const
197 if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
199 OptionalString v = ::IsString( node );
202 const std::string& initialValue = *v;
203 if( (initialValue[ 0 ] == '{') && (initialValue[ initialValue.size() -1 ] == '}') )
205 ret = initialValue.substr( 1, initialValue.size() - 2 );
212 Property::Value Replacement::GetFullReplacement( const std::string& replacementString ) const
215 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
216 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
218 PropertyValueMap::const_iterator iter = FindReplacement( replacementString, *mOverrideMap, *mDefaultMap );
220 if( iter == (*mDefaultMap).end() )
222 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
226 out = (*iter).second;
227 #if defined(DEBUG_ENABLED)
228 DALI_SCRIPT_VERBOSE(" Full replacement for '%s' => to Type '%s'\n",
229 replacementString.c_str(),
230 PropertyTypes::GetName( out.GetType()) );
237 OptionalBoolean Replacement::IsBoolean( const TreeNode & node ) const
240 if( OptionalString replace = HasFullReplacement( node ) )
242 Property::Value value = GetFullReplacement( *replace );
243 if( Property::BOOLEAN == value.GetType() )
245 ret = value.Get<bool>();
250 ret = ::IsBoolean( node );
255 OptionalBoolean Replacement::IsBoolean( OptionalChild child ) const
259 return IsBoolean( *child );
263 return OptionalBoolean();
267 // template <typename T, OptionalValue<T> (*ISTYPE)( const TreeNode& node ), Property::Type TYPE>
268 // OptionalValue<T> IsOfType( const TreeNode& node, const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
270 // OptionalValue<T> ret;
271 // if( OptionalString replace = HasFullReplacement( node, overrideMap, defaultMap ) )
273 // Property::Value value = GetFullReplacement( *replace, overrideMap, defaultMap );
274 // if( TYPE == value.GetType() )
276 // ret = value.Get<T>();
281 // ret = ISTYPE( node );
287 // OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
289 // return IsOfType<float, ::IsFloat, Property::FLOAT>( node, *mOverrideMap, *mDefaultMap );
290 // /* OptionalFloat ret; */
291 // /* if( OptionalString replace = HasFullReplacement( node ) ) */
293 // /* Property::Value value = GetFullReplacement( replace ); */
294 // /* if( Property::FLOAT == value.GetType() ) */
296 // /* ret = value.Get<float>(); */
301 // /* ret = IsFloat( node ); */
306 OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
309 if( OptionalString replace = HasFullReplacement( node ) )
311 Property::Value value = GetFullReplacement( *replace );
312 if( Property::FLOAT == value.GetType() )
314 ret = value.Get<float>();
319 ret = ::IsFloat( node );
324 OptionalString Replacement::IsString( const TreeNode& node ) const
328 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
329 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
331 if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
333 if( OptionalString v = ::IsString( node ) )
335 Property::Value value;
336 if( ResolvePartialReplacement( *v, value, *mOverrideMap, *mDefaultMap ) )
338 if( Property::STRING == value.GetType() )
340 ret = value.Get<std::string>();
341 #if defined(DEBUG_ENABLED)
342 DALI_SCRIPT_VERBOSE(" Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
348 if( Property::STRING == value.GetType() )
350 ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
357 ret = ::IsString( node );
362 OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
365 if( OptionalString replace = HasFullReplacement( node ) )
367 Property::Value value = GetFullReplacement( *replace );
368 if( Property::INTEGER == value.GetType() )
370 ret = value.Get<int>();
375 ret = ::IsInteger( node );
380 OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
383 if( OptionalString replace = HasFullReplacement( node ) )
385 Property::Value value = GetFullReplacement( *replace );
386 if( Property::VECTOR2 == value.GetType() )
388 ret = value.Get<Vector2>();
393 ret = ::IsVector2( node );
398 OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
401 if( OptionalString replace = HasFullReplacement( node ) )
403 Property::Value value = GetFullReplacement( *replace );
404 if( Property::VECTOR3 == value.GetType() )
406 ret = value.Get<Vector3>();
411 ret = ::IsVector3( node );
416 OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
419 if( OptionalString replace = HasFullReplacement( node ) )
421 Property::Value value = GetFullReplacement( *replace );
422 if( Property::VECTOR4 == value.GetType() )
424 ret = value.Get<Vector4>();
429 ret = ::IsVector4( node );
434 OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
437 if( OptionalString replace = HasFullReplacement( node ) )
439 Property::Value value = GetFullReplacement( *replace );
440 if( Property::MATRIX == value.GetType() )
442 ret = value.Get<Matrix>();
447 ret = ::IsMatrix( node );
452 OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
455 if( OptionalString replace = HasFullReplacement( node ) )
457 Property::Value value = GetFullReplacement( *replace );
458 if( Property::MATRIX3 == value.GetType() )
460 ret = value.Get<Matrix3>();
465 ret = ::IsMatrix3( node );
470 OptionalRect Replacement::IsRect( const TreeNode & node ) const
473 if( OptionalString replace = HasFullReplacement( node ) )
475 Property::Value value = GetFullReplacement( *replace );
476 if( Property::RECTANGLE == value.GetType() )
478 ret = value.Get<Rect<int> >();
483 ret = ::IsRect( node );
490 OptionalFloat Replacement::IsFloat( OptionalChild child ) const
494 return IsFloat( *child );
498 return OptionalFloat();
503 OptionalString Replacement::IsString( OptionalChild child ) const
507 return IsString( *child );
511 return OptionalString();
515 OptionalInteger Replacement::IsInteger( OptionalChild child ) const
519 return IsInteger( *child );
523 return OptionalInteger();
527 OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
531 return IsVector2( *child );
535 return OptionalVector2();
539 OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
543 return IsVector3( *child );
547 return OptionalVector3();
551 OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
555 return IsVector4( *child );
559 return OptionalVector4();
563 OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
567 return IsMatrix( *child );
571 return OptionalMatrix();
575 OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
579 return IsMatrix3( *child );
583 return OptionalMatrix3();
587 OptionalRect Replacement::IsRect( OptionalChild child ) const
591 return IsRect( *child );
595 return OptionalRect();
599 bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
605 if( OptionalString replace = HasFullReplacement( *child ) )
607 out = GetFullReplacement( *replace );
608 if( Property::MAP == out.GetType() )
618 bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
624 if( OptionalString replace = HasFullReplacement( *child ) )
626 out = GetFullReplacement( *replace );
627 if( Property::ARRAY == out.GetType() )
637 } // namespace Internal
639 } // namespace Toolkit