Clean up the code to build successfully on macOS
[platform/core/uifw/dali-core.git] / dali / public-api / object / property-map.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/object/property-map.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/vector-wrapper.h>
26
27 namespace Dali
28 {
29 namespace
30 {
31 typedef std::vector<StringValuePair> StringValueContainer;
32
33 using IndexValuePair      = std::pair<Property::Index, Property::Value>;
34 using IndexValueContainer = std::vector<IndexValuePair>;
35
36 }; // unnamed namespace
37
38 struct Property::Map::Impl
39 {
40   StringValueContainer mStringValueContainer;
41   IndexValueContainer  mIndexValueContainer;
42 };
43
44 Property::Map::Map()
45 : mImpl(new Impl)
46 {
47 }
48
49 Property::Map::Map(const std::initializer_list<KeyValuePair>& values)
50 : Map()
51 {
52   for(auto&& value : values)
53   {
54     const auto& key = value.first;
55     switch(key.type)
56     {
57       case Property::Key::INDEX:
58       {
59         Property::Map::Insert(key.indexKey, value.second);
60         break;
61       }
62       case Property::Key::STRING:
63       {
64         Property::Map::Insert(key.stringKey, value.second);
65         break;
66       }
67     }
68   }
69 }
70
71 Property::Map::Map(const Property::Map& other)
72 : mImpl(new Impl)
73 {
74   mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
75   mImpl->mIndexValueContainer  = other.mImpl->mIndexValueContainer;
76 }
77
78 Property::Map::Map(Property::Map&& other)
79 : mImpl(other.mImpl)
80 {
81   other.mImpl = nullptr;
82 }
83
84 Property::Map::~Map()
85 {
86   delete mImpl;
87 }
88
89 Property::Map::SizeType Property::Map::Count() const
90 {
91   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
92   return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
93 }
94
95 bool Property::Map::Empty() const
96 {
97   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
98   return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
99 }
100
101 void Property::Map::Insert(const char* key, const Value& value)
102 {
103   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
104   mImpl->mStringValueContainer.push_back(std::make_pair(key, value));
105 }
106
107 void Property::Map::Insert(const std::string& key, const Value& value)
108 {
109   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
110   mImpl->mStringValueContainer.push_back(std::make_pair(key, value));
111 }
112
113 void Property::Map::Insert(Property::Index key, const Value& value)
114 {
115   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
116   mImpl->mIndexValueContainer.push_back(std::make_pair(key, value));
117 }
118
119 Property::Value& Property::Map::GetValue(SizeType position) const
120 {
121   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
122   SizeType numStringKeys = mImpl->mStringValueContainer.size();
123   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
124   DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
125
126   if(position < numStringKeys)
127   {
128     return mImpl->mStringValueContainer[position].second;
129   }
130   else
131   {
132     return mImpl->mIndexValueContainer[position - numStringKeys].second;
133   }
134 }
135
136 const std::string& Property::Map::GetKey(SizeType position) const
137 {
138   DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n");
139
140   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
141   SizeType numStringKeys = mImpl->mStringValueContainer.size();
142   DALI_ASSERT_ALWAYS(position < numStringKeys && "position out-of-bounds");
143
144   return mImpl->mStringValueContainer[position].first;
145 }
146
147 Property::Key Property::Map::GetKeyAt(SizeType position) const
148 {
149   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
150
151   SizeType numStringKeys = mImpl->mStringValueContainer.size();
152   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
153   DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
154
155   if(position < numStringKeys)
156   {
157     Key key(mImpl->mStringValueContainer[position].first);
158     return key;
159   }
160   else
161   {
162     Key key(mImpl->mIndexValueContainer[position - numStringKeys].first);
163     return key;
164   }
165 }
166
167 StringValuePair& Property::Map::GetPair(SizeType position) const
168 {
169   DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n");
170
171   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
172
173   SizeType numStringKeys = mImpl->mStringValueContainer.size();
174
175   DALI_ASSERT_ALWAYS(position < (numStringKeys) && "position out-of-bounds");
176
177   return mImpl->mStringValueContainer[position];
178 }
179
180 KeyValuePair Property::Map::GetKeyValue(SizeType position) const
181 {
182   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
183
184   SizeType numStringKeys = mImpl->mStringValueContainer.size();
185   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
186
187   DALI_ASSERT_ALWAYS(position < (numStringKeys + numIndexKeys) && "position out-of-bounds");
188
189   if(position < numStringKeys)
190   {
191     Key          key(mImpl->mStringValueContainer[position].first);
192     KeyValuePair keyValue(key, mImpl->mStringValueContainer[position].second);
193     return keyValue;
194   }
195   else
196   {
197     Key          key(mImpl->mIndexValueContainer[position - numStringKeys].first);
198     KeyValuePair keyValue(key, mImpl->mIndexValueContainer[position - numStringKeys].second);
199     return keyValue;
200   }
201 }
202
203 Property::Value* Property::Map::Find(const char* key) const
204 {
205   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
206
207   for(auto&& iter : mImpl->mStringValueContainer)
208   {
209     if(iter.first == key)
210     {
211       return &iter.second;
212     }
213   }
214   return nullptr; // Not found
215 }
216
217 Property::Value* Property::Map::Find(const std::string& key) const
218 {
219   return Find(key.c_str());
220 }
221
222 Property::Value* Property::Map::Find(Property::Index key) const
223 {
224   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
225
226   for(auto&& iter : mImpl->mIndexValueContainer)
227   {
228     if(iter.first == key)
229     {
230       return &iter.second;
231     }
232   }
233   return nullptr; // Not found
234 }
235
236 Property::Value* Property::Map::Find(Property::Index indexKey, const std::string& stringKey) const
237 {
238   Property::Value* valuePtr = Find(indexKey);
239   if(!valuePtr)
240   {
241     valuePtr = Find(stringKey);
242   }
243   return valuePtr;
244 }
245
246 Property::Value* Property::Map::Find(const std::string& key, Property::Type type) const
247 {
248   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
249
250   for(auto&& iter : mImpl->mStringValueContainer)
251   {
252     if((iter.second.GetType() == type) && (iter.first == key))
253     {
254       return &iter.second;
255     }
256   }
257   return nullptr; // Not found
258 }
259
260 Property::Value* Property::Map::Find(Property::Index key, Property::Type type) const
261 {
262   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
263
264   for(auto&& iter : mImpl->mIndexValueContainer)
265   {
266     if((iter.second.GetType() == type) && (iter.first == key))
267     {
268       return &iter.second;
269     }
270   }
271   return nullptr; // Not found
272 }
273
274 void Property::Map::Clear()
275 {
276   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
277
278   mImpl->mStringValueContainer.clear();
279   mImpl->mIndexValueContainer.clear();
280 }
281
282 void Property::Map::Merge(const Property::Map& from)
283 {
284   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
285
286   // Ensure we're not attempting to merge with ourself
287   if(this != &from)
288   {
289     if(Count())
290     {
291       for(auto&& iter : from.mImpl->mStringValueContainer)
292       {
293         (*this)[iter.first] = iter.second;
294       }
295
296       for(auto&& iter : from.mImpl->mIndexValueContainer)
297       {
298         (*this)[iter.first] = iter.second;
299       }
300     }
301     else
302     {
303       // If we're empty, then just copy
304       *this = from;
305     }
306   }
307 }
308
309 const Property::Value& Property::Map::operator[](const std::string& key) const
310 {
311   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
312
313   for(auto&& iter : mImpl->mStringValueContainer)
314   {
315     if(iter.first == key)
316     {
317       return iter.second;
318     }
319   }
320
321   DALI_ASSERT_ALWAYS(!"Invalid Key");
322 }
323
324 Property::Value& Property::Map::operator[](const std::string& key)
325 {
326   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
327
328   for(auto&& iter : mImpl->mStringValueContainer)
329   {
330     if(iter.first == key)
331     {
332       return iter.second;
333     }
334   }
335
336   // Create and return reference to new value
337   mImpl->mStringValueContainer.push_back(std::make_pair(key, Property::Value()));
338   return (mImpl->mStringValueContainer.end() - 1)->second;
339 }
340
341 const Property::Value& Property::Map::operator[](Property::Index key) const
342 {
343   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
344
345   for(auto&& iter : mImpl->mIndexValueContainer)
346   {
347     if(iter.first == key)
348     {
349       return iter.second;
350     }
351   }
352
353   DALI_ASSERT_ALWAYS(!"Invalid Key");
354 }
355
356 Property::Value& Property::Map::operator[](Property::Index key)
357 {
358   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
359
360   for(auto&& iter : mImpl->mIndexValueContainer)
361   {
362     if(iter.first == key)
363     {
364       return iter.second;
365     }
366   }
367
368   // Create and return reference to new value
369   mImpl->mIndexValueContainer.push_back(std::make_pair(key, Property::Value()));
370   return (mImpl->mIndexValueContainer.end() - 1)->second;
371 }
372
373 Property::Map& Property::Map::operator=(const Property::Map& other)
374 {
375   DALI_ASSERT_DEBUG(mImpl && "Cannot use an object previously used as an r-value");
376
377   if(this != &other)
378   {
379     mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
380     mImpl->mIndexValueContainer  = other.mImpl->mIndexValueContainer;
381   }
382   return *this;
383 }
384
385 Property::Map& Property::Map::operator=(Property::Map&& other)
386 {
387   if(this != &other)
388   {
389     delete mImpl;
390     mImpl       = other.mImpl;
391     other.mImpl = nullptr;
392   }
393   return *this;
394 }
395
396 std::ostream& operator<<(std::ostream& stream, const Property::Map& map)
397 {
398   stream << "Map(" << map.Count() << ") = {";
399
400   if(map.mImpl)
401   {
402     int32_t count = 0;
403     // Output the String-Value pairs
404     for(auto&& iter : map.mImpl->mStringValueContainer)
405     {
406       if(count++ > 0)
407       {
408         stream << ", ";
409       }
410       stream << iter.first << ":" << iter.second;
411     }
412
413     // Output the Index-Value pairs
414     for(auto&& iter : map.mImpl->mIndexValueContainer)
415     {
416       if(count++ > 0)
417       {
418         stream << ", ";
419       }
420       stream << iter.first << ":" << iter.second;
421     }
422   }
423
424   stream << "}";
425
426   return stream;
427 }
428
429 } // namespace Dali