2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/public-api/object/property-map.h>
22 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/common/vector-wrapper.h>
32 typedef std::vector< StringValuePair > StringValueContainer;
34 using IndexValuePair = std::pair<Property::Index, Property::Value>;
35 using IndexValueContainer = std::vector<IndexValuePair>;
37 }; // unnamed namespace
40 struct Property::Map::Impl
42 StringValueContainer mStringValueContainer;
43 IndexValueContainer mIndexValueContainer;
51 Property::Map::Map( const std::initializer_list< KeyValuePair >& values ) : Map()
53 for( auto&& value : values )
55 const auto& key = value.first;
58 case Property::Key::INDEX:
60 Property::Map::Insert( key.indexKey, value.second );
63 case Property::Key::STRING:
65 Property::Map::Insert( key.stringKey, value.second );
72 Property::Map::Map( const Property::Map& other )
75 mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
76 mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
79 Property::Map::Map( Property::Map&& other )
80 : mImpl( other.mImpl )
82 other.mImpl = nullptr;
90 Property::Map::SizeType Property::Map::Count() const
92 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
93 return mImpl->mStringValueContainer.size() + mImpl->mIndexValueContainer.size();
96 bool Property::Map::Empty() const
98 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
99 return mImpl->mStringValueContainer.empty() && mImpl->mIndexValueContainer.empty();
102 void Property::Map::Insert( const char* key, const Value& value )
104 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
105 mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
108 void Property::Map::Insert( const std::string& key, const Value& value )
110 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
111 mImpl->mStringValueContainer.push_back( std::make_pair( key, value ) );
114 void Property::Map::Insert( Property::Index key, const Value& value )
116 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
117 mImpl->mIndexValueContainer.push_back( std::make_pair( key, value ) );
120 Property::Value& Property::Map::GetValue( SizeType position ) const
122 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
123 SizeType numStringKeys = mImpl->mStringValueContainer.size();
124 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
125 DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
127 if( position < numStringKeys )
129 return mImpl->mStringValueContainer[ position ].second;
133 return mImpl->mIndexValueContainer[ position-numStringKeys ].second;
137 const std::string& Property::Map::GetKey( SizeType position ) const
139 DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetKey() is deprecated and will be removed from next release.\n" );
141 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
142 SizeType numStringKeys = mImpl->mStringValueContainer.size();
143 DALI_ASSERT_ALWAYS( position < numStringKeys && "position out-of-bounds" );
145 return mImpl->mStringValueContainer[ position ].first;
148 Property::Key Property::Map::GetKeyAt( SizeType position ) const
150 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
152 SizeType numStringKeys = mImpl->mStringValueContainer.size();
153 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
154 DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
156 if( position < numStringKeys )
158 Key key(mImpl->mStringValueContainer[ position ].first);
163 Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
168 StringValuePair& Property::Map::GetPair( SizeType position ) const
170 DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: GetPair() is deprecated and will be removed from next release.\n" );
172 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
174 SizeType numStringKeys = mImpl->mStringValueContainer.size();
176 DALI_ASSERT_ALWAYS( position < ( numStringKeys ) && "position out-of-bounds" );
178 return mImpl->mStringValueContainer[ position ];
181 KeyValuePair Property::Map::GetKeyValue( SizeType position ) const
183 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
185 SizeType numStringKeys = mImpl->mStringValueContainer.size();
186 SizeType numIndexKeys = mImpl->mIndexValueContainer.size();
188 DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
190 if( position < numStringKeys )
192 Key key(mImpl->mStringValueContainer[ position ].first);
193 KeyValuePair keyValue(key, mImpl->mStringValueContainer[ position ].second );
198 Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
199 KeyValuePair keyValue(key, mImpl->mIndexValueContainer[ position-numStringKeys ].second );
204 Property::Value* Property::Map::Find( const char* key ) const
206 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
208 for( auto&& iter : mImpl->mStringValueContainer )
210 if ( iter.first == key )
215 return NULL; // Not found
218 Property::Value* Property::Map::Find( const std::string& key ) const
220 return Find( key.c_str() );
223 Property::Value* Property::Map::Find( Property::Index key ) const
225 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
227 for( auto&& iter : mImpl->mIndexValueContainer )
229 if ( iter.first == key )
234 return NULL; // Not found
237 Property::Value* Property::Map::Find( Property::Index indexKey, const std::string& stringKey ) const
239 Property::Value* valuePtr = Find( indexKey );
242 valuePtr = Find( stringKey );
247 Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
249 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
251 for( auto&& iter : mImpl->mStringValueContainer )
253 if( (iter.second.GetType() == type) && (iter.first == key) )
258 return NULL; // Not found
261 Property::Value* Property::Map::Find( Property::Index key, Property::Type type ) const
263 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
265 for( auto&& iter : mImpl->mIndexValueContainer )
267 if( (iter.second.GetType() == type) && (iter.first == key) )
272 return NULL; // Not found
275 void Property::Map::Clear()
277 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
279 mImpl->mStringValueContainer.clear();
280 mImpl->mIndexValueContainer.clear();
283 void Property::Map::Merge( const Property::Map& from )
285 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
287 // Ensure we're not attempting to merge with ourself
292 for( auto&& iter : from.mImpl->mStringValueContainer )
294 (*this)[iter.first] = iter.second;
297 for( auto&& iter : from.mImpl->mIndexValueContainer )
299 (*this)[iter.first] = iter.second;
304 // If we're empty, then just copy
310 const Property::Value& Property::Map::operator[]( const std::string& key ) const
312 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
314 for( auto&& iter : mImpl->mStringValueContainer )
316 if ( iter.first == key )
322 DALI_ASSERT_ALWAYS( ! "Invalid Key" );
325 Property::Value& Property::Map::operator[]( const std::string& key )
327 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
329 for( auto&& iter : mImpl->mStringValueContainer )
331 if ( iter.first == key )
337 // Create and return reference to new value
338 mImpl->mStringValueContainer.push_back( std::make_pair( key, Property::Value() ) );
339 return (mImpl->mStringValueContainer.end() - 1)->second;
342 const Property::Value& Property::Map::operator[]( Property::Index key ) const
344 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
346 for( auto&& iter : mImpl->mIndexValueContainer )
348 if ( iter.first == key )
354 DALI_ASSERT_ALWAYS( ! "Invalid Key" );
357 Property::Value& Property::Map::operator[]( Property::Index key )
359 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
361 for( auto&& iter : mImpl->mIndexValueContainer )
363 if ( iter.first == key )
369 // Create and return reference to new value
370 mImpl->mIndexValueContainer.push_back( std::make_pair( key, Property::Value() ) );
371 return (mImpl->mIndexValueContainer.end() - 1)->second;
374 Property::Map& Property::Map::operator=( const Property::Map& other )
376 DALI_ASSERT_DEBUG( mImpl && "Cannot use an object previously used as an r-value" );
380 mImpl->mStringValueContainer = other.mImpl->mStringValueContainer;
381 mImpl->mIndexValueContainer = other.mImpl->mIndexValueContainer;
386 Property::Map& Property::Map::operator=( Property::Map&& other )
392 other.mImpl = nullptr;
397 std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
399 stream << "Map(" << map.Count() << ") = {";
404 // Output the String-Value pairs
405 for( auto&& iter : map.mImpl->mStringValueContainer )
411 stream<< iter.first << ":" << iter.second;
414 // Output the Index-Value pairs
415 for( auto&& iter : map.mImpl->mIndexValueContainer )
421 stream<< iter.first << ":" << iter.second;