Making DALi public API typesafe using guaranteed types; uint8_t, uint32_t
[platform/core/uifw/dali-core.git] / dali / public-api / object / property-map.cpp
1 /*
2  * Copyright (c) 2015 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
30 namespace
31 {
32 typedef std::vector< StringValuePair > StringValueContainer;
33
34 typedef std::pair< Property::Index, Property::Value > IndexValuePair;
35 typedef std::vector< IndexValuePair > IndexValueContainer;
36
37 }; // unnamed namespace
38
39
40 struct Property::Map::Impl
41 {
42   StringValueContainer mStringValueContainer;
43   IndexValueContainer mIndexValueContainer;
44 };
45
46 Property::Map::Map()
47 : mImpl( new Impl )
48 {
49 }
50
51 Property::Map::Map( const Property::Map& other )
52 : mImpl( new Impl )
53 {
54   mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
55   mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
56 }
57
58 Property::Map::~Map()
59 {
60   delete mImpl;
61 }
62
63 Property::Map::SizeType Property::Map::Count() const
64 {
65   return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
66 }
67
68 bool Property::Map::Empty() const
69 {
70   return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
71 }
72
73 void Property::Map::Insert( const char* key, const Value& value )
74 {
75   mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
76 }
77
78 void Property::Map::Insert( const std::string& key, const Value& value )
79 {
80   mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
81 }
82
83 void Property::Map::Insert( Property::Index key, const Value& value )
84 {
85   mImpl->mIndexValueContainer.push_back( std::make_pair( key, value ) );
86 }
87
88 Property::Value& Property::Map::GetValue( SizeType position ) const
89 {
90   SizeType numStringKeys = mImpl->mStringValueContainer.size();
91   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
92   DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
93
94   if( position < numStringKeys )
95   {
96     return mImpl->mStringValueContainer[ position ].second;
97   }
98   else
99   {
100     return mImpl->mIndexValueContainer[ position-numStringKeys ].second;
101   }
102 }
103
104 const std::string& Property::Map::GetKey( SizeType position ) const
105 {
106   DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n" );
107
108   SizeType numStringKeys = mImpl->mStringValueContainer.size();
109   DALI_ASSERT_ALWAYS( position < numStringKeys && "position out-of-bounds" );
110
111   return mImpl->mStringValueContainer[ position ].first;
112 }
113
114 Property::Key Property::Map::GetKeyAt( SizeType position ) const
115 {
116   SizeType numStringKeys = mImpl->mStringValueContainer.size();
117   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
118   DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
119
120   if( position < numStringKeys )
121   {
122     Key key(mImpl->mStringValueContainer[ position ].first);
123     return key;
124   }
125   else
126   {
127     Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
128     return key;
129   }
130 }
131
132 StringValuePair& Property::Map::GetPair( SizeType position ) const
133 {
134   DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n" );
135
136   SizeType numStringKeys = mImpl->mStringValueContainer.size();
137
138   DALI_ASSERT_ALWAYS( position < ( numStringKeys ) && "position out-of-bounds" );
139
140   return mImpl->mStringValueContainer[ position ];
141 }
142
143 KeyValuePair Property::Map::GetKeyValue( SizeType position ) const
144 {
145   SizeType numStringKeys = mImpl->mStringValueContainer.size();
146   SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
147
148   DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
149
150   if( position < numStringKeys )
151   {
152     Key key(mImpl->mStringValueContainer[ position ].first);
153     KeyValuePair keyValue(key, mImpl->mStringValueContainer[ position ].second );
154     return keyValue;
155   }
156   else
157   {
158     Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
159     KeyValuePair keyValue(key, mImpl->mIndexValueContainer[ position-numStringKeys ].second );
160     return keyValue;
161   }
162 }
163
164 Property::Value* Property::Map::Find( const char* key ) const
165 {
166   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
167   {
168     if ( iter->first == key )
169     {
170       return &iter->second;
171     }
172   }
173   return NULL; // Not found
174 }
175
176 Property::Value* Property::Map::Find( const std::string& key ) const
177 {
178   return Find( key.c_str() );
179 }
180
181 Property::Value* Property::Map::Find( Property::Index key ) const
182 {
183   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
184   {
185     if ( iter->first == key )
186     {
187       return &iter->second;
188     }
189   }
190   return NULL; // Not found
191 }
192
193 Property::Value* Property::Map::Find( Property::Index indexKey, const std::string& stringKey ) const
194 {
195   Property::Value* valuePtr = Find( indexKey );
196   if( !valuePtr )
197   {
198     valuePtr = Find( stringKey );
199   }
200   return valuePtr;
201 }
202
203 Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
204 {
205   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
206   {
207     if( (iter->second.GetType() == type) && (iter->first == key) )
208     {
209       return &iter->second;
210     }
211   }
212   return NULL; // Not found
213 }
214
215 Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const
216 {
217   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
218   {
219     if( (iter->second.GetType() == type) && (iter->first == key) )
220     {
221       return &iter->second;
222     }
223   }
224   return NULL; // Not found
225 }
226
227 void Property::Map::Clear()
228 {
229   mImpl->mStringValueContainer.clear();
230   mImpl->mIndexValueContainer.clear();
231 }
232
233 void Property::Map::Merge( const Property::Map& from )
234 {
235   // Ensure we're not attempting to merge with ourself
236   if ( this != &from )
237   {
238     if ( Count() )
239     {
240       for ( StringValueContainer::const_iterator iter = from.mImpl->mStringValueContainer.begin(), endIter = from.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
241       {
242         (*this)[iter->first] = iter->second;
243       }
244
245       for ( IndexValueContainer::const_iterator iter = from.mImpl->mIndexValueContainer.begin(), endIter = from.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
246       {
247         (*this)[iter->first] = iter->second;
248       }
249     }
250     else
251     {
252       // If we're empty, then just copy
253       *this = from;
254     }
255   }
256 }
257
258 const Property::Value& Property::Map::operator[]( const std::string& key ) const
259 {
260   for ( StringValueContainer::const_iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
261   {
262     if ( iter->first == key )
263     {
264       return iter->second;
265     }
266   }
267
268   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
269 }
270
271 Property::Value& Property::Map::operator[]( const std::string& key )
272 {
273   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
274   {
275     if ( iter->first == key )
276     {
277       return iter->second;
278     }
279   }
280
281   // Create and return reference to new value
282   mImpl->mStringValueContainer.push_back( std::make_pair( key, Property::Value() ) );
283   return (mImpl->mStringValueContainer.end() - 1)->second;
284 }
285
286 const Property::Value& Property::Map::operator[]( Property::Index key ) const
287 {
288   for ( IndexValueContainer::const_iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
289   {
290     if ( iter->first == key )
291     {
292       return iter->second;
293     }
294   }
295
296   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
297 }
298
299 Property::Value& Property::Map::operator[]( Property::Index key )
300 {
301   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
302   {
303     if ( iter->first == key )
304     {
305       return iter->second;
306     }
307   }
308
309   // Create and return reference to new value
310   mImpl->mIndexValueContainer.push_back( std::make_pair( key, Property::Value() ) );
311   return (mImpl->mIndexValueContainer.end() - 1)->second;
312 }
313
314 Property::Map& Property::Map::operator=( const Property::Map& other )
315 {
316   if( this != &other )
317   {
318     delete mImpl;
319     mImpl = new Impl;
320     mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
321     mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
322   }
323   return *this;
324 }
325
326 std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
327 {
328   stream << "Map(" << map.Count() << ") = {";
329
330   int32_t count = 0;
331   // Output the String-Value pairs
332   for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
333   {
334     if( count++ > 0 )
335     {
336       stream<<", ";
337     }
338     stream<< iter->first << ":"<<iter->second;
339   }
340
341   // Output the Index-Value pairs
342   for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
343   {
344     if( count++ > 0 )
345     {
346       stream<<", ";
347     }
348     stream<< iter->first << ":"<<iter->second;
349   }
350
351   stream << "}";
352
353   return stream;
354 }
355
356 } // namespace Dali