2 * Copyright (c) 2021 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 const std::string str(initialValue.substr(startPos, size));
117 Property::Value* value = FindReplacement(str, overrideMap, defaultMap);
121 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", str.c_str());
125 if(Property::STRING != value->GetType())
127 DALI_SCRIPT_WARNING("Cannot replace substring in non string property type='%s'. Initial value '%s'\n",
128 PropertyTypes::GetName(out.GetType()),
129 initialValue.c_str());
133 std::string newString =
134 initialValue.substr(0, startPos - 1) +
135 value->Get<std::string>() +
136 initialValue.substr(startPos + size + 1);
138 return ResolvePartialReplacement(newString, out, overrideMap, defaultMap);
144 // if we get here we failed
150 Replacement::Replacement(const Property::Map& overrideMap, const Property::Map& defaultMap)
151 : mOverrideMap(&overrideMap),
152 mDefaultMap(&defaultMap)
161 Replacement::Replacement(const Property::Map& defaultMap)
162 : mOverrideMap(&noMap),
163 mDefaultMap(&defaultMap)
167 Replacement::Replacement()
168 : mOverrideMap(&noMap),
173 OptionalString Replacement::HasFullReplacement(const TreeNode& node) const
177 if(node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()))
179 OptionalString v = ::IsString(node);
182 const std::string& initialValue = *v;
183 if((initialValue[0] == '{') && (initialValue[initialValue.size() - 1] == '}'))
185 ret = initialValue.substr(1, initialValue.size() - 2);
192 Property::Value Replacement::GetFullReplacement(const std::string& replacementString) const
195 DALI_ASSERT_DEBUG(mOverrideMap && "missing map");
196 DALI_ASSERT_DEBUG(mDefaultMap && "missing map");
198 Property::Value* value = FindReplacement(replacementString, *mOverrideMap, *mDefaultMap);
202 DALI_SCRIPT_WARNING("Cannot find replacement for '%s'\n", replacementString.c_str());
207 #if defined(DEBUG_ENABLED)
208 DALI_SCRIPT_VERBOSE(" Full replacement for '%s' => to Type '%s'\n",
209 replacementString.c_str(),
210 PropertyTypes::GetName(out.GetType()));
217 OptionalBoolean Replacement::IsBoolean(const TreeNode& node) const
220 if(OptionalString replace = HasFullReplacement(node))
222 Property::Value value = GetFullReplacement(*replace);
223 if(Property::BOOLEAN == value.GetType())
225 ret = value.Get<bool>();
230 ret = ::IsBoolean(node);
235 OptionalBoolean Replacement::IsBoolean(OptionalChild child) const
239 return IsBoolean(*child);
243 return OptionalBoolean();
247 OptionalFloat Replacement::IsFloat(const TreeNode& node) const
250 if(OptionalString replace = HasFullReplacement(node))
252 Property::Value value = GetFullReplacement(*replace);
253 if(Property::FLOAT == value.GetType())
255 ret = value.Get<float>();
260 ret = ::IsFloat(node);
265 OptionalString Replacement::IsString(const TreeNode& node) const
269 DALI_ASSERT_DEBUG(mOverrideMap && "missing map");
270 DALI_ASSERT_DEBUG(mDefaultMap && "missing map");
272 if(node.HasSubstitution() && ((*mOverrideMap).Count() || (*mDefaultMap).Count()))
274 if(OptionalString v = ::IsString(node))
276 Property::Value value;
277 if(ResolvePartialReplacement(*v, value, *mOverrideMap, *mDefaultMap))
279 if(Property::STRING == value.GetType())
281 ret = value.Get<std::string>();
282 #if defined(DEBUG_ENABLED)
283 DALI_SCRIPT_VERBOSE(" Resolved substring replacement for '%s' => '%s'\n", (*v).c_str(), (*ret).c_str());
289 ret = v; // sets the unexpanded. Expansion may occur later in processing with include files
295 ret = ::IsString(node);
300 OptionalInteger Replacement::IsInteger(const TreeNode& node) const
303 if(OptionalString replace = HasFullReplacement(node))
305 Property::Value value = GetFullReplacement(*replace);
306 if(Property::INTEGER == value.GetType())
308 ret = value.Get<int>();
313 ret = ::IsInteger(node);
318 OptionalVector2 Replacement::IsVector2(const TreeNode& node) const
321 if(OptionalString replace = HasFullReplacement(node))
323 Property::Value value = GetFullReplacement(*replace);
324 if(Property::VECTOR2 == value.GetType())
326 ret = value.Get<Vector2>();
331 ret = ::IsVector2(node);
336 OptionalVector3 Replacement::IsVector3(const TreeNode& node) const
339 if(OptionalString replace = HasFullReplacement(node))
341 Property::Value value = GetFullReplacement(*replace);
342 if(Property::VECTOR3 == value.GetType())
344 ret = value.Get<Vector3>();
349 ret = ::IsVector3(node);
354 OptionalVector4 Replacement::IsVector4(const TreeNode& node) const
357 if(OptionalString replace = HasFullReplacement(node))
359 Property::Value value = GetFullReplacement(*replace);
360 if(Property::VECTOR4 == value.GetType())
362 ret = value.Get<Vector4>();
367 ret = ::IsVector4(node);
372 OptionalMatrix Replacement::IsMatrix(const TreeNode& node) const
375 if(OptionalString replace = HasFullReplacement(node))
377 Property::Value value = GetFullReplacement(*replace);
378 if(Property::MATRIX == value.GetType())
380 ret = value.Get<Matrix>();
385 ret = ::IsMatrix(node);
390 OptionalMatrix3 Replacement::IsMatrix3(const TreeNode& node) const
393 if(OptionalString replace = HasFullReplacement(node))
395 Property::Value value = GetFullReplacement(*replace);
396 if(Property::MATRIX3 == value.GetType())
398 ret = value.Get<Matrix3>();
403 ret = ::IsMatrix3(node);
408 OptionalRect Replacement::IsRect(const TreeNode& node) const
411 if(OptionalString replace = HasFullReplacement(node))
413 Property::Value value = GetFullReplacement(*replace);
414 if(Property::RECTANGLE == value.GetType())
416 ret = value.Get<Rect<int> >();
421 ret = ::IsRect(node);
426 OptionalExtents Replacement::IsExtents(const TreeNode& node) const
428 OptionalExtents extents;
429 if(OptionalString replace = HasFullReplacement(node))
431 Property::Value value = GetFullReplacement(*replace);
432 if(Property::EXTENTS == value.GetType())
434 extents = value.Get<Extents>();
439 extents = ::IsExtents(node);
444 OptionalFloat Replacement::IsFloat(OptionalChild child) const
448 return IsFloat(*child);
452 return OptionalFloat();
456 OptionalString Replacement::IsString(OptionalChild child) const
460 return IsString(*child);
464 return OptionalString();
468 OptionalInteger Replacement::IsInteger(OptionalChild child) const
472 return IsInteger(*child);
476 return OptionalInteger();
480 OptionalVector2 Replacement::IsVector2(OptionalChild child) const
484 return IsVector2(*child);
488 return OptionalVector2();
492 OptionalVector3 Replacement::IsVector3(OptionalChild child) const
496 return IsVector3(*child);
500 return OptionalVector3();
504 OptionalVector4 Replacement::IsVector4(OptionalChild child) const
508 return IsVector4(*child);
512 return OptionalVector4();
516 OptionalMatrix Replacement::IsMatrix(OptionalChild child) const
520 return IsMatrix(*child);
524 return OptionalMatrix();
528 OptionalMatrix3 Replacement::IsMatrix3(OptionalChild child) const
532 return IsMatrix3(*child);
536 return OptionalMatrix3();
540 OptionalRect Replacement::IsRect(OptionalChild child) const
544 return IsRect(*child);
548 return OptionalRect();
552 bool Replacement::IsMap(OptionalChild child, Property::Value& out) const
558 if(OptionalString replace = HasFullReplacement(*child))
560 out = GetFullReplacement(*replace);
561 if(Property::MAP == out.GetType())
571 bool Replacement::IsArray(OptionalChild child, Property::Value& out) const
577 if(OptionalString replace = HasFullReplacement(*child))
579 out = GetFullReplacement(*replace);
580 if(Property::ARRAY == out.GetType())
590 OptionalExtents Replacement::IsExtents(OptionalChild child) const
594 return IsExtents(*child);
598 return OptionalExtents();
602 } // namespace Internal
604 } // namespace Toolkit