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());
350 ret = ::IsString( node );
355 OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
358 if( OptionalString replace = HasFullReplacement( node ) )
360 Property::Value value = GetFullReplacement( *replace );
361 if( Property::INTEGER == value.GetType() )
363 ret = value.Get<int>();
368 ret = ::IsInteger( node );
373 OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
376 if( OptionalString replace = HasFullReplacement( node ) )
378 Property::Value value = GetFullReplacement( *replace );
379 if( Property::VECTOR2 == value.GetType() )
381 ret = value.Get<Vector2>();
386 ret = ::IsVector2( node );
391 OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
394 if( OptionalString replace = HasFullReplacement( node ) )
396 Property::Value value = GetFullReplacement( *replace );
397 if( Property::VECTOR3 == value.GetType() )
399 ret = value.Get<Vector3>();
404 ret = ::IsVector3( node );
409 OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
412 if( OptionalString replace = HasFullReplacement( node ) )
414 Property::Value value = GetFullReplacement( *replace );
415 if( Property::VECTOR4 == value.GetType() )
417 ret = value.Get<Vector4>();
422 ret = ::IsVector4( node );
427 OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
430 if( OptionalString replace = HasFullReplacement( node ) )
432 Property::Value value = GetFullReplacement( *replace );
433 if( Property::MATRIX == value.GetType() )
435 ret = value.Get<Matrix>();
440 ret = ::IsMatrix( node );
445 OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
448 if( OptionalString replace = HasFullReplacement( node ) )
450 Property::Value value = GetFullReplacement( *replace );
451 if( Property::MATRIX3 == value.GetType() )
453 ret = value.Get<Matrix3>();
458 ret = ::IsMatrix3( node );
463 OptionalRect Replacement::IsRect( const TreeNode & node ) const
466 if( OptionalString replace = HasFullReplacement( node ) )
468 Property::Value value = GetFullReplacement( *replace );
469 if( Property::RECTANGLE == value.GetType() )
471 ret = value.Get<Rect<int> >();
476 ret = ::IsRect( node );
483 OptionalFloat Replacement::IsFloat( OptionalChild child ) const
487 return IsFloat( *child );
491 return OptionalFloat();
496 OptionalString Replacement::IsString( OptionalChild child ) const
500 return IsString( *child );
504 return OptionalString();
508 OptionalInteger Replacement::IsInteger( OptionalChild child ) const
512 return IsInteger( *child );
516 return OptionalInteger();
520 OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
524 return IsVector2( *child );
528 return OptionalVector2();
532 OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
536 return IsVector3( *child );
540 return OptionalVector3();
544 OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
548 return IsVector4( *child );
552 return OptionalVector4();
556 OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
560 return IsMatrix( *child );
564 return OptionalMatrix();
568 OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
572 return IsMatrix3( *child );
576 return OptionalMatrix3();
580 OptionalRect Replacement::IsRect( OptionalChild child ) const
584 return IsRect( *child );
588 return OptionalRect();
592 bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
598 if( OptionalString replace = HasFullReplacement( *child ) )
600 out = GetFullReplacement( *replace );
601 if( Property::MAP == out.GetType() )
611 bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
617 if( OptionalString replace = HasFullReplacement( *child ) )
619 out = GetFullReplacement( *replace );
620 if( Property::ARRAY == out.GetType() )
630 } // namespace Internal
632 } // namespace Toolkit