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