Merge "Fix a crash in ImageVisual in case of an invalid image and changed to render...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / dictionary.h
1 #ifndef DALI_TOOLKIT_INTERNAL_BUILDER_DICTIONARY_H
2 #define DALI_TOOLKIT_INTERNAL_BUILDER_DICTIONARY_H
3
4 /*
5  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <dali/public-api/common/vector-wrapper.h>
21 #include <algorithm>
22
23 namespace Dali
24 {
25 extern bool CaseInsensitiveStringCompare( const std::string& a, const std::string& b );
26
27 namespace Toolkit
28 {
29 namespace Internal
30 {
31
32 /**
33  * The Dictionary template class enables a means of storing key-value
34  * pairs where the keys are strings and the value can be a complex
35  * type.
36  *
37  * It enables lookup of keys via case-insensitive match.
38  */
39
40
41 typedef std::vector<std::string> DictionaryKeys;
42 inline void Merge( DictionaryKeys& toDict, const DictionaryKeys& fromDict )
43 {
44   for( DictionaryKeys::const_iterator fromIter = fromDict.begin(); fromIter != fromDict.end(); ++fromIter )
45   {
46     const std::string& fromKey = (*fromIter);
47     DictionaryKeys::iterator toIter = std::find( toDict.begin(), toDict.end(), fromKey );
48     if( toIter == toDict.end() )
49     {
50       toDict.push_back( fromKey );
51     }
52   }
53 }
54
55
56 template<typename EntryType>
57 class Dictionary
58 {
59 private:
60   /**
61    * Element is a key-value pair
62    */
63   struct Element
64   {
65     std::string key;
66     EntryType entry;
67     Element( const std::string&name, EntryType entry )
68     : key( name ),
69       entry( entry )
70     {
71     }
72   };
73   typedef std::vector<Element> Elements;
74   Elements container;
75
76 public:
77   /**
78    * Only allow const iteration over the dictionary
79    */
80   typedef typename Elements::const_iterator iterator;
81
82   /**
83    * Constructor
84    */
85   Dictionary<EntryType>()
86   {
87   }
88
89   /**
90    * Add a key value pair to the dictionary.
91    * If the entry does not already exist, add it to the dictionary
92    * using a shallow copy
93    */
94   bool Add( const std::string& name, const EntryType& entry )
95   {
96     for( typename Elements::iterator iter = container.begin(); iter != container.end(); ++iter )
97     {
98       if( iter->key == name )
99       {
100         return false;
101       }
102     }
103     container.push_back( Element(name, entry) );
104     return true;
105   }
106
107   /**
108    * Add a key-value pair to the dictionary
109    * If the entry does not already exist, add it to the dictionary
110    * (shallow copy)
111    */
112   bool Add( const char* name, const EntryType& entry )
113   {
114     bool result=false;
115     if( name != NULL )
116     {
117       std::string theName(name);
118       result=Add(theName, entry);
119     }
120     return result;
121   }
122
123   /**
124    * Remove a key value pair from the dictionary.
125    */
126   void Remove( const std::string& name )
127   {
128     for( typename Elements::iterator iter = container.begin(); iter != container.end(); ++iter )
129     {
130       if( iter->key == name )
131       {
132         container.erase( iter );
133         break;
134       }
135     }
136   }
137
138   /**
139    * Remove a key value pair from the dictionary.
140    */
141   void Remove( const char* name )
142   {
143     if( name != NULL )
144     {
145       std::string theName(name);
146       Remove(theName);
147     }
148   }
149
150   void Merge( const Dictionary<EntryType>& dictionary )
151   {
152     for( typename Elements::const_iterator fromIter = dictionary.container.begin(); fromIter != dictionary.container.end(); ++fromIter )
153     {
154       bool found=false;
155       for( typename Elements::iterator toIter = container.begin(); toIter != container.end(); ++toIter )
156       {
157         if( fromIter->key == toIter->key )
158         {
159           found=true;
160           toIter->entry = fromIter->entry;
161         }
162       }
163       if( !found )
164       {
165         container.push_back( Element(fromIter->key, fromIter->entry) );
166       }
167     }
168   }
169
170   /**
171    * Find the element in the dictionary pointed at by key, and
172    * insensitive search, and return a const pointer to it, or NULL
173    */
174   const EntryType* FindConst( const std::string& key ) const
175   {
176     if( ! key.empty() )
177     {
178       for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
179       {
180         if( Dali::CaseInsensitiveStringCompare(iter->key, key ))
181         {
182           const EntryType* result = &(iter->entry);
183           return result;
184         }
185       }
186     }
187     return NULL;
188   }
189
190   /**
191    * Find the element in the dictionary pointed at by key using a case
192    * insensitive search, and return a non-const pointer to it, or NULL
193    */
194   EntryType* Find( const std::string& key ) const
195   {
196     EntryType* result = NULL;
197     if( ! key.empty() )
198     {
199       for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
200       {
201         if( Dali::CaseInsensitiveStringCompare(iter->key, key ))
202         {
203           // Const cast because of const_iterator. const_iterator because, STL.
204           result = const_cast<EntryType*>(&(iter->entry));
205         }
206       }
207     }
208     return result;
209   }
210
211   /**
212    * Find the element in the dictionary pointed at by key using a case
213    * insensitive search, and return a const pointer to it, or NULL
214    */
215   const EntryType* FindConst( const char* key ) const
216   {
217     if( key != NULL )
218     {
219       std::string theKey(key);
220       return FindConst( theKey );
221     }
222     return NULL;
223   }
224
225   /**
226    * Find the element in the dictionary pointed at by key using a case
227    * insensitive search, and return a non-const pointer to it, or NULL
228    */
229   EntryType* Find( const char* key ) const
230   {
231     if( key != NULL )
232     {
233       std::string theKey(key);
234       return Find( theKey );
235     }
236     return NULL;
237   }
238   /**
239    * Return an iterator pointing at the first entry in the dictionary
240    */
241   typename Elements::const_iterator Begin() const
242   {
243     return container.begin();
244   }
245
246   /**
247    * Return an iterator pointing past the last entry in the dictionary
248    */
249   typename Elements::const_iterator End() const
250   {
251     return container.end();
252   }
253
254   void GetKeys( DictionaryKeys& keys ) const
255   {
256     keys.clear();
257     for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
258     {
259       keys.push_back( (*iter).key );
260     }
261   }
262
263   void Clear()
264   {
265     container.clear();
266   }
267 };
268
269
270
271 }//Internal
272 }//Toolkit
273 }//Dali
274
275 #endif // DALI_TOOLKIT_INTERNAL_BUILDER_DICTIONARY_H