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