(Property Map) Added method to find and return an index or equivalent string key
[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 struct Property::Map::Impl
37 {
38   StringValueContainer mStringValueContainer;
39   IndexValueContainer mIndexValueContainer;
40 };
41
42 Property::Map::Map()
43 : mImpl( new Impl )
44 {
45 }
46
47 Property::Map::Map( const Property::Map& other )
48 : mImpl( new Impl )
49 {
50   mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
51   mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
52 }
53
54 Property::Map::~Map()
55 {
56   delete mImpl;
57 }
58
59 Property::Map::SizeType Property::Map::Count() const
60 {
61   return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
62 }
63
64 bool Property::Map::Empty() const
65 {
66   return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
67 }
68
69 void Property::Map::Insert( const char* key, const Value& value )
70 {
71   mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
72 }
73
74 void Property::Map::Insert( const std::string& key, const Value& value )
75 {
76   mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
77 }
78
79 void Property::Map::Insert( Property::Index key, const Value& value )
80 {
81   mImpl->mIndexValueContainer.push_back( std::make_pair( key, value ) );
82 }
83
84 Property::Value& Property::Map::GetValue( SizeType position ) const
85 {
86   DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
87
88   return mImpl->mStringValueContainer[ position ].second;
89 }
90
91 const std::string& Property::Map::GetKey( SizeType position ) const
92 {
93   DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
94
95   return mImpl->mStringValueContainer[ position ].first;
96 }
97
98 StringValuePair& Property::Map::GetPair( SizeType position ) const
99 {
100   DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
101
102   return mImpl->mStringValueContainer[ position ];
103 }
104
105 Property::Value* Property::Map::Find( const char* key ) const
106 {
107   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
108   {
109     if ( iter->first == key )
110     {
111       return &iter->second;
112     }
113   }
114   return NULL; // Not found
115 }
116
117 Property::Value* Property::Map::Find( const std::string& key ) const
118 {
119   return Find( key.c_str() );
120 }
121
122 Property::Value* Property::Map::Find( Property::Index key ) const
123 {
124   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
125   {
126     if ( iter->first == key )
127     {
128       return &iter->second;
129     }
130   }
131   return NULL; // Not found
132 }
133
134 Property::Value* Property::Map::Find( Property::Index indexKey, const std::string& stringKey ) const
135 {
136   Property::Value* valuePtr = Find( indexKey );
137   if( !valuePtr )
138   {
139     valuePtr = Find( stringKey );
140   }
141   return valuePtr;
142 }
143
144 Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
145 {
146   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
147   {
148     if( (iter->second.GetType() == type) && (iter->first == key) )
149     {
150       return &iter->second;
151     }
152   }
153   return NULL; // Not found
154 }
155
156 Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const
157 {
158   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
159   {
160     if( (iter->second.GetType() == type) && (iter->first == key) )
161     {
162       return &iter->second;
163     }
164   }
165   return NULL; // Not found
166 }
167
168 void Property::Map::Clear()
169 {
170   mImpl->mStringValueContainer.clear();
171   mImpl->mIndexValueContainer.clear();
172 }
173
174 void Property::Map::Merge( const Property::Map& from )
175 {
176   // Ensure we're not attempting to merge with ourself
177   if ( this != &from )
178   {
179     if ( Count() )
180     {
181       for ( StringValueContainer::const_iterator iter = from.mImpl->mStringValueContainer.begin(), endIter = from.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
182       {
183         (*this)[iter->first] = iter->second;
184       }
185
186       for ( IndexValueContainer::const_iterator iter = from.mImpl->mIndexValueContainer.begin(), endIter = from.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
187       {
188         (*this)[iter->first] = iter->second;
189       }
190     }
191     else
192     {
193       // If we're empty, then just copy
194       *this = from;
195     }
196   }
197 }
198
199 const Property::Value& Property::Map::operator[]( const std::string& key ) const
200 {
201   for ( StringValueContainer::const_iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
202   {
203     if ( iter->first == key )
204     {
205       return iter->second;
206     }
207   }
208
209   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
210 }
211
212 Property::Value& Property::Map::operator[]( const std::string& key )
213 {
214   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
215   {
216     if ( iter->first == key )
217     {
218       return iter->second;
219     }
220   }
221
222   // Create and return reference to new value
223   mImpl->mStringValueContainer.push_back( std::make_pair( key, Property::Value() ) );
224   return (mImpl->mStringValueContainer.end() - 1)->second;
225 }
226
227 const Property::Value& Property::Map::operator[]( Property::Index key ) const
228 {
229   for ( IndexValueContainer::const_iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
230   {
231     if ( iter->first == key )
232     {
233       return iter->second;
234     }
235   }
236
237   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
238 }
239
240 Property::Value& Property::Map::operator[]( Property::Index key )
241 {
242   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
243   {
244     if ( iter->first == key )
245     {
246       return iter->second;
247     }
248   }
249
250   // Create and return reference to new value
251   mImpl->mIndexValueContainer.push_back( std::make_pair( key, Property::Value() ) );
252   return (mImpl->mIndexValueContainer.end() - 1)->second;
253 }
254
255 Property::Map& Property::Map::operator=( const Property::Map& other )
256 {
257   if( this != &other )
258   {
259     delete mImpl;
260     mImpl = new Impl;
261     mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
262     mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
263   }
264   return *this;
265 }
266
267 std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
268 {
269   stream << "Map(" << map.Count() << ") = {";
270
271   int count = 0;
272   // Output the String-Value pairs
273   for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
274   {
275     if( count++ > 0 )
276     {
277       stream<<", ";
278     }
279     stream<< iter->first << ":"<<iter->second;
280   }
281
282   // Output the Index-Value pairs
283   for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
284   {
285     if( count++ > 0 )
286     {
287       stream<<", ";
288     }
289     stream<< iter->first << ":"<<iter->second;
290   }
291
292   stream << "}";
293
294   return stream;
295 }
296
297 } // namespace Dali