2 * Copyright (c) 2024 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/builder-get-is.inl.h>
20 #include <dali-toolkit/internal/builder/builder-impl.h>
21 #include <dali-toolkit/internal/builder/replacement.h>
31 Property::Value* FindReplacement(const std::string& str, const Property::Map& overrideMap, const Property::Map& defaultMap)
33 Property::Value* ret = overrideMap.Find(str);
37 ret = defaultMap.Find(str);
40 // try localized text ie dgettext. Look for colon {DOMAIN:TEXT} {LC_MESSAGE:ID_XXXX}
46 std::size_t FirstUnescapedChar(const std::string& initialValue, const std::size_t& startPos, const char c)
48 std::size_t pos = initialValue.find(c, startPos);
52 while(pos != std::string::npos)
54 if('\\' == initialValue.at(pos - 1))
56 pos = initialValue.find(c, pos);
68 bool GetSubstitutionPosition(const std::string& initialValue, std::size_t& startPos, std::size_t& size)
70 std::size_t pos = FirstUnescapedChar(initialValue, 0, '{');
72 if(std::string::npos == pos)
74 startPos = std::string::npos;
82 pos = FirstUnescapedChar(initialValue, startPos, '}');
84 if(std::string::npos == pos)
86 size = std::string::npos;
91 size = pos - startPos;
97 bool ResolvePartialReplacement(const std::string& initialValue, Property::Value& out, const Property::Map& overrideMap, const Property::Map& defaultMap)
99 if(initialValue.size() >= 2)
101 // eg '{"constants": { "IMAGE_DIR": "/share/images" },
103 // "filename":"{IMAGE_DIR}/theme/header.png",
105 std::size_t startPos = 0;
106 std::size_t size = std::string::npos;
108 if(!GetSubstitutionPosition(initialValue, startPos, size))
115 DALI_ASSERT_ALWAYS((startPos > 0u && size > 0u) && "Replacement keyword getter have some problem!\n");
117 const std::string str(initialValue.substr(startPos, size));
119 Property::Value* value = FindReplacement(str, overrideMap, defaultMap);
123 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", str.c_str());
127 if(Property::STRING != value->GetType())
129 DALI_SCRIPT_WARNING("Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
130 PropertyTypes::GetName(out.GetType()),
131 initialValue.c_str());
135 std::string newString =
136 initialValue.substr(0, startPos - 1) +
137 value->Get<std::string>() +
138 initialValue.substr(startPos + size + 1);
140 return ResolvePartialReplacement(newString, out, overrideMap, defaultMap);
146 // if we get here we failed
152 Replacement::Replacement(const Property::Map& overrideMap, const Property::Map& defaultMap)
153 : mOverrideMap(&overrideMap),
154 mDefaultMap(&defaultMap)
163 Replacement::Replacement(const Property::Map& defaultMap)
164 : mOverrideMap(&noMap),
165 mDefaultMap(&defaultMap)
169 Replacement::Replacement()
170 : mOverrideMap(&noMap),
175 OptionalString Replacement::HasFullReplacement(const TreeNode& node) const
179 if(node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()))
181 OptionalString v = ::IsString(node);
184 const std::string& initialValue = *v;
185 if((initialValue[0] == '{') && (initialValue[initialValue.size() - 1] == '}'))
187 ret = initialValue.substr(1, initialValue.size() - 2);
194 Property::Value Replacement::GetFullReplacement(const std::string& replacementString) const
197 DALI_ASSERT_DEBUG(mOverrideMap && "missing map");
198 DALI_ASSERT_DEBUG(mDefaultMap && "missing map");
200 Property::Value* value = FindReplacement(replacementString, *mOverrideMap, *mDefaultMap);
204 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
209 #if defined(DEBUG_ENABLED)
210 DALI_SCRIPT_VERBOSE(" Full replacement for '%s' => to Type '%s'\n",
211 replacementString.c_str(),
212 PropertyTypes::GetName(out.GetType()));
219 OptionalBoolean Replacement::IsBoolean(const TreeNode& node) const
222 if(OptionalString replace = HasFullReplacement(node))
224 Property::Value value = GetFullReplacement(*replace);
225 if(Property::BOOLEAN == value.GetType())
227 ret = value.Get<bool>();
232 ret = ::IsBoolean(node);
237 OptionalBoolean Replacement::IsBoolean(OptionalChild child) const
241 return IsBoolean(*child);
245 return OptionalBoolean();
249 OptionalFloat Replacement::IsFloat(const TreeNode& node) const
252 if(OptionalString replace = HasFullReplacement(node))
254 Property::Value value = GetFullReplacement(*replace);
255 if(Property::FLOAT == value.GetType())
257 ret = value.Get<float>();
262 ret = ::IsFloat(node);
267 OptionalString Replacement::IsString(const TreeNode& node) const
271 DALI_ASSERT_DEBUG(mOverrideMap && "missing map");
272 DALI_ASSERT_DEBUG(mDefaultMap && "missing map");
274 if(node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()))
276 if(OptionalString v = ::IsString(node))
278 Property::Value value;
279 if(ResolvePartialReplacement(*v, value, *mOverrideMap, *mDefaultMap))
281 if(Property::STRING == value.GetType())
283 ret = value.Get<std::string>();
284 #if defined(DEBUG_ENABLED)
285 DALI_SCRIPT_VERBOSE(" Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
291 ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
297 ret = ::IsString(node);
302 OptionalInteger Replacement::IsInteger(const TreeNode& node) const
305 if(OptionalString replace = HasFullReplacement(node))
307 Property::Value value = GetFullReplacement(*replace);
308 if(Property::INTEGER == value.GetType())
310 ret = value.Get<int>();
315 ret = ::IsInteger(node);
320 OptionalVector2 Replacement::IsVector2(const TreeNode& node) const
323 if(OptionalString replace = HasFullReplacement(node))
325 Property::Value value = GetFullReplacement(*replace);
326 if(Property::VECTOR2 == value.GetType())
328 ret = value.Get<Vector2>();
333 ret = ::IsVector2(node);
338 OptionalVector3 Replacement::IsVector3(const TreeNode& node) const
341 if(OptionalString replace = HasFullReplacement(node))
343 Property::Value value = GetFullReplacement(*replace);
344 if(Property::VECTOR3 == value.GetType())
346 ret = value.Get<Vector3>();
351 ret = ::IsVector3(node);
356 OptionalVector4 Replacement::IsVector4(const TreeNode& node) const
359 if(OptionalString replace = HasFullReplacement(node))
361 Property::Value value = GetFullReplacement(*replace);
362 if(Property::VECTOR4 == value.GetType())
364 ret = value.Get<Vector4>();
369 ret = ::IsVector4(node);
374 OptionalMatrix Replacement::IsMatrix(const TreeNode& node) const
377 if(OptionalString replace = HasFullReplacement(node))
379 Property::Value value = GetFullReplacement(*replace);
380 if(Property::MATRIX == value.GetType())
382 ret = value.Get<Matrix>();
387 ret = ::IsMatrix(node);
392 OptionalMatrix3 Replacement::IsMatrix3(const TreeNode& node) const
395 if(OptionalString replace = HasFullReplacement(node))
397 Property::Value value = GetFullReplacement(*replace);
398 if(Property::MATRIX3 == value.GetType())
400 ret = value.Get<Matrix3>();
405 ret = ::IsMatrix3(node);
410 OptionalRect Replacement::IsRect(const TreeNode& node) const
413 if(OptionalString replace = HasFullReplacement(node))
415 Property::Value value = GetFullReplacement(*replace);
416 if(Property::RECTANGLE == value.GetType())
418 ret = value.Get<Rect<int> >();
423 ret = ::IsRect(node);
428 OptionalExtents Replacement::IsExtents(const TreeNode& node) const
430 OptionalExtents extents;
431 if(OptionalString replace = HasFullReplacement(node))
433 Property::Value value = GetFullReplacement(*replace);
434 if(Property::EXTENTS == value.GetType())
436 extents = value.Get<Extents>();
441 extents = ::IsExtents(node);
446 OptionalFloat Replacement::IsFloat(OptionalChild child) const
450 return IsFloat(*child);
454 return OptionalFloat();
458 OptionalString Replacement::IsString(OptionalChild child) const
462 return IsString(*child);
466 return OptionalString();
470 OptionalInteger Replacement::IsInteger(OptionalChild child) const
474 return IsInteger(*child);
478 return OptionalInteger();
482 OptionalVector2 Replacement::IsVector2(OptionalChild child) const
486 return IsVector2(*child);
490 return OptionalVector2();
494 OptionalVector3 Replacement::IsVector3(OptionalChild child) const
498 return IsVector3(*child);
502 return OptionalVector3();
506 OptionalVector4 Replacement::IsVector4(OptionalChild child) const
510 return IsVector4(*child);
514 return OptionalVector4();
518 OptionalMatrix Replacement::IsMatrix(OptionalChild child) const
522 return IsMatrix(*child);
526 return OptionalMatrix();
530 OptionalMatrix3 Replacement::IsMatrix3(OptionalChild child) const
534 return IsMatrix3(*child);
538 return OptionalMatrix3();
542 OptionalRect Replacement::IsRect(OptionalChild child) const
546 return IsRect(*child);
550 return OptionalRect();
554 bool Replacement::IsMap(OptionalChild child, Property::Value& out) const
560 if(OptionalString replace = HasFullReplacement(*child))
562 out = GetFullReplacement(*replace);
563 if(Property::MAP == out.GetType())
573 bool Replacement::IsArray(OptionalChild child, Property::Value& out) const
579 if(OptionalString replace = HasFullReplacement(*child))
581 out = GetFullReplacement(*replace);
582 if(Property::ARRAY == out.GetType())
592 OptionalExtents Replacement::IsExtents(OptionalChild child) const
596 return IsExtents(*child);
600 return OptionalExtents();
604 } // namespace Internal
606 } // namespace Toolkit