2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
35 Property::Value* FindReplacement( const std::string &str, const Property::Map& overrideMap, const Property::Map& defaultMap )
37 Property::Value* ret = overrideMap.Find( str );
41 ret = defaultMap.Find( str );
44 // try localized text ie dgettext. Look for colon {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
50 std::size_t FirstUnescapedChar(const std::string &initialValue, const std::size_t& startPos, const char c)
52 std::size_t pos = initialValue.find( c, startPos );
56 while( pos != std::string::npos )
58 if( '\\' == initialValue.at( pos-1 ) )
60 pos = initialValue.find( c, pos );
72 bool GetSubstitutionPosition( const std::string &initialValue, std::size_t &startPos, std::size_t &size )
74 std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
76 if( std::string::npos == pos )
78 startPos = std::string::npos;
86 pos = FirstUnescapedChar(initialValue, startPos, '}');
88 if( std::string::npos == pos )
90 size = std::string::npos;
95 size = pos - startPos;
101 bool ResolvePartialReplacement( const std::string &initialValue, Property::Value &out,
102 const Property::Map& overrideMap, const Property::Map& defaultMap )
105 if( initialValue.size() >= 2 )
107 // eg '{"constants": { "IMAGE_DIR": "/share/images" },
109 // "filename":"{IMAGE_DIR}/theme/header.png",
111 std::size_t startPos = 0;
112 std::size_t size = std::string::npos;
114 if( !GetSubstitutionPosition( initialValue, startPos, size ) )
121 const std::string str( initialValue.substr( startPos, size ) );
123 Property::Value* value = FindReplacement( str, overrideMap, defaultMap );
127 DALI_SCRIPT_WARNING( "Cannot find replacement for '%s'\n", str.c_str() );
131 if( Property::STRING != value->GetType() )
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() );
138 std::string newString = \
139 initialValue.substr(0, startPos - 1) +
140 value->Get< std::string >() +
141 initialValue.substr( startPos + size + 1 );
143 return ResolvePartialReplacement( newString, out, overrideMap, defaultMap );
149 // if we get here we failed
156 Replacement::Replacement( const Property::Map& overrideMap, const Property::Map& defaultMap )
157 : mOverrideMap( &overrideMap ), mDefaultMap( &defaultMap )
167 Replacement::Replacement( const Property::Map& defaultMap )
168 : mOverrideMap( &noMap ), mDefaultMap( &defaultMap )
173 Replacement::Replacement( )
174 : mOverrideMap( &noMap ), mDefaultMap( &noMap )
179 OptionalString Replacement::HasFullReplacement( const TreeNode & node ) const
183 if( node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()) )
185 OptionalString v = ::IsString( node );
188 const std::string& initialValue = *v;
189 if( (initialValue[ 0 ] == '{') && (initialValue[ initialValue.size() -1 ] == '}') )
191 ret = initialValue.substr( 1, initialValue.size() - 2 );
198 Property::Value Replacement::GetFullReplacement( const std::string& replacementString ) const
201 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
202 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
204 Property::Value* value = FindReplacement( replacementString, *mOverrideMap, *mDefaultMap );
208 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
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()) );
223 OptionalBoolean Replacement::IsBoolean( const TreeNode & node ) const
226 if( OptionalString replace = HasFullReplacement( node ) )
228 Property::Value value = GetFullReplacement( *replace );
229 if( Property::BOOLEAN == value.GetType() )
231 ret = value.Get<bool>();
236 ret = ::IsBoolean( node );
241 OptionalBoolean Replacement::IsBoolean( OptionalChild child ) const
245 return IsBoolean( *child );
249 return OptionalBoolean();
253 OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
256 if( OptionalString replace = HasFullReplacement( node ) )
258 Property::Value value = GetFullReplacement( *replace );
259 if( Property::FLOAT == value.GetType() )
261 ret = value.Get<float>();
266 ret = ::IsFloat( node );
271 OptionalString Replacement::IsString( const TreeNode& node ) const
275 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
276 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
278 if( node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()) )
280 if( OptionalString v = ::IsString( node ) )
282 Property::Value value;
283 if( ResolvePartialReplacement( *v, value, *mOverrideMap, *mDefaultMap ) )
285 if( Property::STRING == value.GetType() )
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());
295 ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
301 ret = ::IsString( node );
306 OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
309 if( OptionalString replace = HasFullReplacement( node ) )
311 Property::Value value = GetFullReplacement( *replace );
312 if( Property::INTEGER == value.GetType() )
314 ret = value.Get<int>();
319 ret = ::IsInteger( node );
324 OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
327 if( OptionalString replace = HasFullReplacement( node ) )
329 Property::Value value = GetFullReplacement( *replace );
330 if( Property::VECTOR2 == value.GetType() )
332 ret = value.Get<Vector2>();
337 ret = ::IsVector2( node );
342 OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
345 if( OptionalString replace = HasFullReplacement( node ) )
347 Property::Value value = GetFullReplacement( *replace );
348 if( Property::VECTOR3 == value.GetType() )
350 ret = value.Get<Vector3>();
355 ret = ::IsVector3( node );
360 OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
363 if( OptionalString replace = HasFullReplacement( node ) )
365 Property::Value value = GetFullReplacement( *replace );
366 if( Property::VECTOR4 == value.GetType() )
368 ret = value.Get<Vector4>();
373 ret = ::IsVector4( node );
378 OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
381 if( OptionalString replace = HasFullReplacement( node ) )
383 Property::Value value = GetFullReplacement( *replace );
384 if( Property::MATRIX == value.GetType() )
386 ret = value.Get<Matrix>();
391 ret = ::IsMatrix( node );
396 OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
399 if( OptionalString replace = HasFullReplacement( node ) )
401 Property::Value value = GetFullReplacement( *replace );
402 if( Property::MATRIX3 == value.GetType() )
404 ret = value.Get<Matrix3>();
409 ret = ::IsMatrix3( node );
414 OptionalRect Replacement::IsRect( const TreeNode & node ) const
417 if( OptionalString replace = HasFullReplacement( node ) )
419 Property::Value value = GetFullReplacement( *replace );
420 if( Property::RECTANGLE == value.GetType() )
422 ret = value.Get<Rect<int> >();
427 ret = ::IsRect( node );
434 OptionalFloat Replacement::IsFloat( OptionalChild child ) const
438 return IsFloat( *child );
442 return OptionalFloat();
447 OptionalString Replacement::IsString( OptionalChild child ) const
451 return IsString( *child );
455 return OptionalString();
459 OptionalInteger Replacement::IsInteger( OptionalChild child ) const
463 return IsInteger( *child );
467 return OptionalInteger();
471 OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
475 return IsVector2( *child );
479 return OptionalVector2();
483 OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
487 return IsVector3( *child );
491 return OptionalVector3();
495 OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
499 return IsVector4( *child );
503 return OptionalVector4();
507 OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
511 return IsMatrix( *child );
515 return OptionalMatrix();
519 OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
523 return IsMatrix3( *child );
527 return OptionalMatrix3();
531 OptionalRect Replacement::IsRect( OptionalChild child ) const
535 return IsRect( *child );
539 return OptionalRect();
543 bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
549 if( OptionalString replace = HasFullReplacement( *child ) )
551 out = GetFullReplacement( *replace );
552 if( Property::MAP == out.GetType() )
562 bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
568 if( OptionalString replace = HasFullReplacement( *child ) )
570 out = GetFullReplacement( *replace );
571 if( Property::ARRAY == out.GetType() )
581 } // namespace Internal
583 } // namespace Toolkit