2 * Copyright (c) 2022 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/public-api/object/property-map.h>
22 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/vector-wrapper.h>
31 typedef std::vector<StringValuePair> StringValueContainer;
33 using IndexValuePair = std::pair<Property::Index, Property::Value>;
34 using IndexValueContainer = std::vector<IndexValuePair>;
36 }; // unnamed namespace
38 struct Property::Map::Impl
40 StringValueContainer mStringValueContainer;
41 IndexValueContainer mIndexValueContainer;
49 Property::Map::Map(const std::initializer_list<KeyValuePair>& values)
52 for(auto&& value : values)
54 const auto& key = value.first;
57 case Property::Key::INDEX:
59 Property::Map::Insert(key.indexKey, value.second);
62 case Property::Key::STRING:
64 Property::Map::Insert(key.stringKey, value.second);
71 Property::Map::Map(const Property::Map& other)
74 mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
75 mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
78 Property::Map::Map(Property::Map&& other)
81 other.mImpl = nullptr;
89 Property::Map::SizeType Property::Map::Count() const
91 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
92 return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
95 bool Property::Map::Empty() const
97 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
98 return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
101 void Property::Map::Insert(std::string key, Value value)
103 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
104 mImpl->mStringValueContainer.push_back(std::make_pair(std::move(key), std::move(value)));
107 void Property::Map::Insert(Property::Index key, Value value)
109 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
110 mImpl->mIndexValueContainer.push_back(std::make_pair(key, std::move(value)));
113 Property::Value& Property::Map::GetValue(SizeType position) const
115 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
116 SizeType numStringKeys = mImpl->mStringValueContainer.size();
117 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
118 DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
120 if(position < numStringKeys)
122 return mImpl->mStringValueContainer[position].second;
126 return mImpl->mIndexValueContainer[position - numStringKeys].second;
130 const std::string& Property::Map::GetKey(SizeType position) const
132 DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n");
134 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
135 SizeType numStringKeys = mImpl->mStringValueContainer.size();
136 DALI_ASSERT_ALWAYS(position < numStringKeys && "position out-of-bounds");
138 return mImpl->mStringValueContainer[position].first;
141 Property::Key Property::Map::GetKeyAt(SizeType position) const
143 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
145 SizeType numStringKeys = mImpl->mStringValueContainer.size();
146 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
147 DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
149 if(position < numStringKeys)
151 Key key(mImpl->mStringValueContainer[position].first);
156 Key key(mImpl->mIndexValueContainer[position - numStringKeys].first);
161 StringValuePair& Property::Map::GetPair(SizeType position) const
163 DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n");
165 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
167 SizeType numStringKeys = mImpl->mStringValueContainer.size();
169 DALI_ASSERT_ALWAYS(position < (numStringKeys) && "position out-of-bounds");
171 return mImpl->mStringValueContainer[position];
174 KeyValuePair Property::Map::GetKeyValue(SizeType position) const
176 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
178 SizeType numStringKeys = mImpl->mStringValueContainer.size();
179 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
181 DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
183 if(position < numStringKeys)
185 Key key(mImpl->mStringValueContainer[position].first);
186 KeyValuePair keyValue(key, mImpl->mStringValueContainer[position].second);
191 return mImpl->mIndexValueContainer[position - numStringKeys];
195 Property::Value* Property::Map::Find(std::string_view key) const
197 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
199 for(auto&& iter : mImpl->mStringValueContainer)
201 if(key == iter.first)
206 return nullptr; // Not found
209 Property::Value* Property::Map::Find(Property::Index key) const
211 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
213 for(auto&& iter : mImpl->mIndexValueContainer)
215 if(iter.first == key)
220 return nullptr; // Not found
223 Property::Value* Property::Map::Find(Property::Index indexKey, std::string_view stringKey) const
225 Property::Value* valuePtr = Find(indexKey);
228 valuePtr = Find(stringKey);
233 Property::Value* Property::Map::Find(std::string_view key, Property::Type type) const
235 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
237 for(auto&& iter : mImpl->mStringValueContainer)
239 if((iter.second.GetType() == type) && (key == iter.first))
244 return nullptr; // Not found
247 Property::Value* Property::Map::Find(Property::Index key, Property::Type type) const
249 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
251 for(auto&& iter : mImpl->mIndexValueContainer)
253 if((iter.second.GetType() == type) && (iter.first == key))
258 return nullptr; // Not found
261 void Property::Map::Clear()
263 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
265 mImpl->mStringValueContainer.clear();
266 mImpl->mIndexValueContainer.clear();
269 bool Property::Map::Remove(Property::Index key)
271 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
273 auto iter = std::find_if(mImpl->mIndexValueContainer.begin(), mImpl->mIndexValueContainer.end(), [key](const IndexValuePair& element) { return element.first == key; });
274 if(iter != mImpl->mIndexValueContainer.end())
276 mImpl->mIndexValueContainer.erase(iter);
282 bool Property::Map::Remove(std::string_view key)
284 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
286 auto iter = std::find_if(mImpl->mStringValueContainer.begin(), mImpl->mStringValueContainer.end(), [key](const StringValuePair& element) { return element.first == key; });
287 if(iter != mImpl->mStringValueContainer.end())
289 mImpl->mStringValueContainer.erase(iter);
295 void Property::Map::Merge(const Property::Map& from)
297 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
299 // Ensure we're not attempting to merge with ourself
304 for(auto&& iter : from.mImpl->mStringValueContainer)
306 (*this)[iter.first] = iter.second;
309 for(auto&& iter : from.mImpl->mIndexValueContainer)
311 (*this)[iter.first] = iter.second;
316 // If we're empty, then just copy
322 const Property::Value& Property::Map::operator[](std::string_view key) const
324 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
326 for(auto&& iter : mImpl->mStringValueContainer)
328 if(iter.first == key)
334 DALI_ASSERT_ALWAYS(!"Invalid Key");
337 Property::Value& Property::Map::operator[](std::string_view key)
339 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
341 for(auto&& iter : mImpl->mStringValueContainer)
343 if(iter.first == key)
349 // Create and return reference to new value
350 mImpl->mStringValueContainer.push_back(std::make_pair(std::string(key), Property::Value()));
351 return mImpl->mStringValueContainer.back().second;
354 const Property::Value& Property::Map::operator[](Property::Index key) const
356 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
358 for(auto&& iter : mImpl->mIndexValueContainer)
360 if(iter.first == key)
366 DALI_ASSERT_ALWAYS(!"Invalid Key");
369 Property::Value& Property::Map::operator[](Property::Index key)
371 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
373 for(auto&& iter : mImpl->mIndexValueContainer)
375 if(iter.first == key)
381 // Create and return reference to new value
382 mImpl->mIndexValueContainer.push_back(std::make_pair(key, Property::Value()));
383 return mImpl->mIndexValueContainer.back().second;
386 Property::Map& Property::Map::operator=(const Property::Map& other)
388 DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
392 mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
393 mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
398 Property::Map& Property::Map::operator=(Property::Map&& other)
404 other.mImpl = nullptr;
409 std::ostream& operator<<(std::ostream& stream, const Property::Map& map)
411 stream << "Map(" << map.Count() << ") = {";
416 // Output the String-Value pairs
417 for(auto&& iter : map.mImpl->mStringValueContainer)
423 stream << iter.first << ":" << iter.second;
426 // Output the Index-Value pairs
427 for(auto&& iter : map.mImpl->mIndexValueContainer)
433 stream << iter.first << ":" << iter.second;