f892aae91b67002f0a9998e2d0b46db2e6a5a7cb
[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( const std::string& key, Property::Type type ) const
135 {
136   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
137   {
138     if( (iter->second.GetType() == type) && (iter->first == key) )
139     {
140       return &iter->second;
141     }
142   }
143   return NULL; // Not found
144 }
145
146 Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const
147 {
148   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
149   {
150     if( (iter->second.GetType() == type) && (iter->first == key) )
151     {
152       return &iter->second;
153     }
154   }
155   return NULL; // Not found
156 }
157
158 void Property::Map::Clear()
159 {
160   mImpl->mStringValueContainer.clear();
161   mImpl->mIndexValueContainer.clear();
162 }
163
164 void Property::Map::Merge( const Property::Map& from )
165 {
166   // Ensure we're not attempting to merge with ourself
167   if ( this != &from )
168   {
169     if ( Count() )
170     {
171       for ( StringValueContainer::const_iterator iter = from.mImpl->mStringValueContainer.begin(), endIter = from.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
172       {
173         (*this)[iter->first] = iter->second;
174       }
175
176       for ( IndexValueContainer::const_iterator iter = from.mImpl->mIndexValueContainer.begin(), endIter = from.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
177       {
178         (*this)[iter->first] = iter->second;
179       }
180     }
181     else
182     {
183       // If we're empty, then just copy
184       *this = from;
185     }
186   }
187 }
188
189 const Property::Value& Property::Map::operator[]( const std::string& key ) const
190 {
191   for ( StringValueContainer::const_iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
192   {
193     if ( iter->first == key )
194     {
195       return iter->second;
196     }
197   }
198
199   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
200 }
201
202 Property::Value& Property::Map::operator[]( const std::string& key )
203 {
204   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
205   {
206     if ( iter->first == key )
207     {
208       return iter->second;
209     }
210   }
211
212   // Create and return reference to new value
213   mImpl->mStringValueContainer.push_back( std::make_pair( key, Property::Value() ) );
214   return (mImpl->mStringValueContainer.end() - 1)->second;
215 }
216
217 const Property::Value& Property::Map::operator[]( Property::Index key ) const
218 {
219   for ( IndexValueContainer::const_iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
220   {
221     if ( iter->first == key )
222     {
223       return iter->second;
224     }
225   }
226
227   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
228 }
229
230 Property::Value& Property::Map::operator[]( Property::Index key )
231 {
232   for ( IndexValueContainer::iterator iter = mImpl->mIndexValueContainer.begin(), endIter = mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
233   {
234     if ( iter->first == key )
235     {
236       return iter->second;
237     }
238   }
239
240   // Create and return reference to new value
241   mImpl->mIndexValueContainer.push_back( std::make_pair( key, Property::Value() ) );
242   return (mImpl->mIndexValueContainer.end() - 1)->second;
243 }
244
245 Property::Map& Property::Map::operator=( const Property::Map& other )
246 {
247   if( this != &other )
248   {
249     delete mImpl;
250     mImpl = new Impl;
251     mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
252     mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
253   }
254   return *this;
255 }
256
257 std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
258 {
259   stream << "Map(" << map.Count() << ") = {";
260
261   int count = 0;
262   // Output the String-Value pairs
263   for ( StringValueContainer::iterator iter = map.mImpl->mStringValueContainer.begin(), endIter = map.mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
264   {
265     if( count++ > 0 )
266     {
267       stream<<", ";
268     }
269     stream<< iter->first << ":"<<iter->second;
270   }
271
272   // Output the Index-Value pairs
273   for ( IndexValueContainer::iterator iter = map.mImpl->mIndexValueContainer.begin(), endIter = map.mImpl->mIndexValueContainer.end(); iter != endIter; ++iter )
274   {
275     if( count++ > 0 )
276     {
277       stream<<", ";
278     }
279     stream<< iter->first << ":"<<iter->second;
280   }
281
282   stream << "}";
283
284   return stream;
285 }
286
287 } // namespace Dali