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 PropertyValueMap::const_iterator FindReplacement( const std::string &str,
36 const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
38 PropertyValueMap::const_iterator ret = defaultMap.end();
40 PropertyValueMap::const_iterator iter = overrideMap.find( str );
42 if( iter != overrideMap.end() )
48 PropertyValueMap::const_iterator iter = defaultMap.find( str );
50 if( iter != defaultMap.end() )
57 // try localized text ie dgettext. Look for colon {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
65 std::size_t FirstUnescapedChar(const std::string &initialValue, const std::size_t& startPos, const char c)
67 std::size_t pos = initialValue.find( c, startPos );
71 while( pos != std::string::npos )
73 if( '\\' == initialValue.at( pos-1 ) )
75 pos = initialValue.find( c, pos );
87 bool GetSubstitutionPosition( const std::string &initialValue, std::size_t &startPos, std::size_t &size )
89 std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
91 if( std::string::npos == pos )
93 startPos = std::string::npos;
101 pos = FirstUnescapedChar(initialValue, startPos, '}');
103 if( std::string::npos == pos )
105 size = std::string::npos;
110 size = pos - startPos;
116 bool ResolvePartialReplacement( const std::string &initialValue, Property::Value &out,
117 const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
120 if( initialValue.size() >= 2 )
122 // eg '{"constants": { "IMAGE_DIR": "/share/images" },
124 // "filename":"{IMAGE_DIR}/theme/header.png",
126 std::size_t startPos = 0;
127 std::size_t size = std::string::npos;
129 if( !GetSubstitutionPosition( initialValue, startPos, size ) )
136 const std::string str( initialValue.substr( startPos, size ) );
138 PropertyValueMap::const_iterator iter = FindReplacement( str, overrideMap, defaultMap );
140 if( iter == defaultMap.end() )
142 DALI_SCRIPT_WARNING( "Cannot find replacement for '%s'\n", str.c_str() );
146 if( Property::STRING != (*iter).second.GetType() )
148 DALI_SCRIPT_WARNING( "Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
149 PropertyTypes::GetName( out.GetType() ), initialValue.c_str() );
153 std::string newString = \
154 initialValue.substr(0, startPos - 1) +
155 (*iter).second.Get<std::string>() +
156 initialValue.substr( startPos + size + 1 );
158 return ResolvePartialReplacement( newString, out, overrideMap, defaultMap );
164 // if we get here we failed
171 Replacement::Replacement( const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
172 : mOverrideMap( &overrideMap ), mDefaultMap( &defaultMap )
179 PropertyValueMap noMap;
182 Replacement::Replacement( const PropertyValueMap& defaultMap )
183 : mOverrideMap( &noMap ), mDefaultMap( &defaultMap )
188 Replacement::Replacement( )
189 : mOverrideMap( &noMap ), mDefaultMap( &noMap )
194 OptionalString Replacement::HasFullReplacement( const TreeNode & node ) const
198 if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
200 OptionalString v = ::IsString( node );
203 const std::string& initialValue = *v;
204 if( (initialValue[ 0 ] == '{') && (initialValue[ initialValue.size() -1 ] == '}') )
206 ret = initialValue.substr( 1, initialValue.size() - 2 );
213 Property::Value Replacement::GetFullReplacement( const std::string& replacementString ) const
216 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
217 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
219 PropertyValueMap::const_iterator iter = FindReplacement( replacementString, *mOverrideMap, *mDefaultMap );
221 if( iter == (*mDefaultMap).end() )
223 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
227 out = (*iter).second;
228 #if defined(DEBUG_ENABLED)
229 DALI_SCRIPT_VERBOSE(" Full replacement for '%s' => to Type '%s'\n",
230 replacementString.c_str(),
231 PropertyTypes::GetName( out.GetType()) );
238 OptionalBoolean Replacement::IsBoolean( const TreeNode & node ) const
241 if( OptionalString replace = HasFullReplacement( node ) )
243 Property::Value value = GetFullReplacement( *replace );
244 if( Property::BOOLEAN == value.GetType() )
246 ret = value.Get<bool>();
251 ret = ::IsBoolean( node );
256 OptionalBoolean Replacement::IsBoolean( OptionalChild child ) const
260 return IsBoolean( *child );
264 return OptionalBoolean();
268 // template <typename T, OptionalValue<T> (*ISTYPE)( const TreeNode& node ), Property::Type TYPE>
269 // OptionalValue<T> IsOfType( const TreeNode& node, const PropertyValueMap& overrideMap, const PropertyValueMap& defaultMap )
271 // OptionalValue<T> ret;
272 // if( OptionalString replace = HasFullReplacement( node, overrideMap, defaultMap ) )
274 // Property::Value value = GetFullReplacement( *replace, overrideMap, defaultMap );
275 // if( TYPE == value.GetType() )
277 // ret = value.Get<T>();
282 // ret = ISTYPE( node );
288 // OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
290 // return IsOfType<float, ::IsFloat, Property::FLOAT>( node, *mOverrideMap, *mDefaultMap );
291 // /* OptionalFloat ret; */
292 // /* if( OptionalString replace = HasFullReplacement( node ) ) */
294 // /* Property::Value value = GetFullReplacement( replace ); */
295 // /* if( Property::FLOAT == value.GetType() ) */
297 // /* ret = value.Get<float>(); */
302 // /* ret = IsFloat( node ); */
307 OptionalFloat Replacement::IsFloat( const TreeNode & node ) const
310 if( OptionalString replace = HasFullReplacement( node ) )
312 Property::Value value = GetFullReplacement( *replace );
313 if( Property::FLOAT == value.GetType() )
315 ret = value.Get<float>();
320 ret = ::IsFloat( node );
325 OptionalString Replacement::IsString( const TreeNode& node ) const
329 DALI_ASSERT_DEBUG( mOverrideMap && "missing map");
330 DALI_ASSERT_DEBUG( mDefaultMap && "missing map");
332 if( node.HasSubstitution() && ((*mOverrideMap).size() || (*mDefaultMap).size()) )
334 if( OptionalString v = ::IsString( node ) )
336 Property::Value value;
337 if( ResolvePartialReplacement( *v, value, *mOverrideMap, *mDefaultMap ) )
339 if( Property::STRING == value.GetType() )
341 ret = value.Get<std::string>();
342 #if defined(DEBUG_ENABLED)
343 DALI_SCRIPT_VERBOSE(" Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
349 if( Property::STRING == value.GetType() )
351 ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
358 ret = ::IsString( node );
363 OptionalInteger Replacement::IsInteger( const TreeNode & node ) const
366 if( OptionalString replace = HasFullReplacement( node ) )
368 Property::Value value = GetFullReplacement( *replace );
369 if( Property::INTEGER == value.GetType() )
371 ret = value.Get<int>();
376 ret = ::IsInteger( node );
381 OptionalUnsignedInt Replacement::IsUnsignedInteger( const TreeNode & node ) const
383 OptionalUnsignedInt ret;
384 if( OptionalString replace = HasFullReplacement( node ) )
386 Property::Value value = GetFullReplacement( *replace );
387 if( Property::UNSIGNED_INTEGER == value.GetType() )
389 ret = value.Get<unsigned int>();
394 if ( OptionalInteger i = ::IsInteger( node ) )
396 ret = OptionalUnsignedInt(static_cast<unsigned int>(*i) );
402 OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
405 if( OptionalString replace = HasFullReplacement( node ) )
407 Property::Value value = GetFullReplacement( *replace );
408 if( Property::VECTOR2 == value.GetType() )
410 ret = value.Get<Vector2>();
415 ret = ::IsVector2( node );
420 OptionalVector3 Replacement::IsVector3( const TreeNode & node ) const
423 if( OptionalString replace = HasFullReplacement( node ) )
425 Property::Value value = GetFullReplacement( *replace );
426 if( Property::VECTOR3 == value.GetType() )
428 ret = value.Get<Vector3>();
433 ret = ::IsVector3( node );
438 OptionalVector4 Replacement::IsVector4( const TreeNode & node ) const
441 if( OptionalString replace = HasFullReplacement( node ) )
443 Property::Value value = GetFullReplacement( *replace );
444 if( Property::VECTOR4 == value.GetType() )
446 ret = value.Get<Vector4>();
451 ret = ::IsVector4( node );
456 OptionalMatrix Replacement::IsMatrix( const TreeNode & node ) const
459 if( OptionalString replace = HasFullReplacement( node ) )
461 Property::Value value = GetFullReplacement( *replace );
462 if( Property::MATRIX == value.GetType() )
464 ret = value.Get<Matrix>();
469 ret = ::IsMatrix( node );
474 OptionalMatrix3 Replacement::IsMatrix3( const TreeNode & node ) const
477 if( OptionalString replace = HasFullReplacement( node ) )
479 Property::Value value = GetFullReplacement( *replace );
480 if( Property::MATRIX3 == value.GetType() )
482 ret = value.Get<Matrix3>();
487 ret = ::IsMatrix3( node );
492 OptionalRect Replacement::IsRect( const TreeNode & node ) const
495 if( OptionalString replace = HasFullReplacement( node ) )
497 Property::Value value = GetFullReplacement( *replace );
498 if( Property::RECTANGLE == value.GetType() )
500 ret = value.Get<Rect<int> >();
505 ret = ::IsRect( node );
512 OptionalFloat Replacement::IsFloat( OptionalChild child ) const
516 return IsFloat( *child );
520 return OptionalFloat();
525 OptionalString Replacement::IsString( OptionalChild child ) const
529 return IsString( *child );
533 return OptionalString();
537 OptionalInteger Replacement::IsInteger( OptionalChild child ) const
541 return IsInteger( *child );
545 return OptionalInteger();
549 OptionalVector2 Replacement::IsVector2( OptionalChild child ) const
553 return IsVector2( *child );
557 return OptionalVector2();
561 OptionalVector3 Replacement::IsVector3( OptionalChild child ) const
565 return IsVector3( *child );
569 return OptionalVector3();
573 OptionalVector4 Replacement::IsVector4( OptionalChild child ) const
577 return IsVector4( *child );
581 return OptionalVector4();
585 OptionalMatrix Replacement::IsMatrix( OptionalChild child ) const
589 return IsMatrix( *child );
593 return OptionalMatrix();
597 OptionalMatrix3 Replacement::IsMatrix3( OptionalChild child ) const
601 return IsMatrix3( *child );
605 return OptionalMatrix3();
609 OptionalRect Replacement::IsRect( OptionalChild child ) const
613 return IsRect( *child );
617 return OptionalRect();
621 bool Replacement::IsMap( OptionalChild child, Property::Value& out ) const
627 if( OptionalString replace = HasFullReplacement( *child ) )
629 out = GetFullReplacement( *replace );
630 if( Property::MAP == out.GetType() )
640 bool Replacement::IsArray( OptionalChild child, Property::Value& out ) const
646 if( OptionalString replace = HasFullReplacement( *child ) )
648 out = GetFullReplacement( *replace );
649 if( Property::ARRAY == out.GetType() )
659 } // namespace Internal
661 } // namespace Toolkit