[dali_1.1.28] 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 > Container;
30 }; // unnamed namespace
31
32 struct Property::Map::Impl
33 {
34   Container mContainer;
35 };
36
37 Property::Map::Map()
38 : mImpl( new Impl )
39 {
40 }
41
42 Property::Map::Map( const Property::Map& other )
43 : mImpl( new Impl )
44 {
45   mImpl->mContainer = other.mImpl->mContainer;
46 }
47
48 Property::Map::~Map()
49 {
50   delete mImpl;
51 }
52
53 Property::Map::SizeType Property::Map::Count() const
54 {
55   return mImpl->mContainer.size();
56 }
57
58 bool Property::Map::Empty() const
59 {
60   return mImpl->mContainer.empty();
61 }
62
63 void Property::Map::Insert( const char* key, const Value& value )
64 {
65   mImpl->mContainer.push_back( std::make_pair( key, value ) );
66 }
67
68 void Property::Map::Insert( const std::string& key, const Value& value )
69 {
70   mImpl->mContainer.push_back( std::make_pair( key, value ) );
71 }
72
73 Property::Value& Property::Map::GetValue( SizeType position ) const
74 {
75   DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
76
77   return mImpl->mContainer[ position ].second;
78 }
79
80 const std::string& Property::Map::GetKey( SizeType position ) const
81 {
82   DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
83
84   return mImpl->mContainer[ position ].first;
85 }
86
87 StringValuePair& Property::Map::GetPair( SizeType position ) const
88 {
89   DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
90
91   return mImpl->mContainer[ position ];
92 }
93
94 Property::Value* Property::Map::Find( const char* key ) const
95 {
96   for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
97   {
98     if ( iter->first == key )
99     {
100       return &iter->second;
101     }
102   }
103   return NULL; // Not found
104 }
105
106 Property::Value* Property::Map::Find( const std::string& key ) const
107 {
108   return Find( key.c_str() );
109
110 }
111
112 Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
113 {
114   for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
115   {
116     // test type first to shortcut eval (possibly reducing string compares)
117     if( (iter->second.GetType() == type) && (iter->first == key) )
118     {
119       return &iter->second;
120     }
121   }
122   return NULL; // Not found
123 }
124
125 void Property::Map::Clear()
126 {
127   mImpl->mContainer.clear();
128 }
129
130 void Property::Map::Merge( const Property::Map& from )
131 {
132   // Ensure we're not attempting to merge with ourself
133   if ( this != &from )
134   {
135     if ( Count() )
136     {
137       for ( unsigned int i = 0, count = from.Count(); i < count; ++i )
138       {
139         StringValuePair& pair( from.GetPair( i ) );
140         (*this)[ pair.first ] = pair.second;
141       }
142     }
143     else
144     {
145       // If we're empty, then just copy
146       *this = from;
147     }
148   }
149 }
150
151 const Property::Value& Property::Map::operator[]( const std::string& key ) const
152 {
153   for ( Container::const_iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
154   {
155     if ( iter->first == key )
156     {
157       return iter->second;
158     }
159   }
160
161   DALI_ASSERT_ALWAYS( ! "Invalid Key" );
162 }
163
164 Property::Value& Property::Map::operator[]( const std::string& key )
165 {
166   for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
167   {
168     if ( iter->first == key )
169     {
170       return iter->second;
171     }
172   }
173
174   // Create and return reference to new value
175   mImpl->mContainer.push_back( std::make_pair( key, Property::Value() ) );
176   return (mImpl->mContainer.end() - 1)->second;
177 }
178
179 Property::Map& Property::Map::operator=( const Property::Map& other )
180 {
181   if( this != &other )
182   {
183     delete mImpl;
184     mImpl = new Impl;
185     mImpl->mContainer = other.mImpl->mContainer;
186   }
187   return *this;
188 }
189
190 std::ostream& operator<<( std::ostream& stream, const Property::Map& map )
191 {
192   stream << "Map(" << map.Count() << ") = {";
193   for( unsigned int i=0; i<map.Count(); ++i )
194   {
195     if( i>0 )
196     {
197       stream << ", ";
198     }
199     stream << map.GetKey(i) << ":" << map.GetValue( i );
200   }
201   stream << "}";
202
203   return stream;
204 }
205
206 } // namespace Dali