Merge "use string_view to avoid temporary string allocation." into devel/master
[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
22 #include <algorithm>
23 #include <string_view>
24
25 namespace Dali
26 {
27 extern bool CaseInsensitiveStringCompare(std::string_view a, std::string_view b);
28
29 namespace Toolkit
30 {
31 namespace Internal
32 {
33
34 /**
35  * The Dictionary template class enables a means of storing key-value
36  * pairs where the keys are strings and the value can be a complex
37  * type.
38  *
39  * It enables lookup of keys via case-insensitive match.
40  */
41
42
43 typedef std::vector<std::string> DictionaryKeys;
44 inline void Merge( DictionaryKeys& toDict, const DictionaryKeys& fromDict )
45 {
46   for( DictionaryKeys::const_iterator fromIter = fromDict.begin(); fromIter != fromDict.end(); ++fromIter )
47   {
48     const std::string& fromKey = (*fromIter);
49     DictionaryKeys::iterator toIter = std::find( toDict.begin(), toDict.end(), fromKey );
50     if( toIter == toDict.end() )
51     {
52       toDict.push_back( fromKey );
53     }
54   }
55 }
56
57
58 template<typename EntryType>
59 class Dictionary
60 {
61 private:
62   /**
63    * Element is a key-value pair
64    */
65   struct Element
66   {
67     std::string key;
68     EntryType entry;
69     Element( const std::string&name, EntryType entry )
70     : key( name ),
71       entry( entry )
72     {
73     }
74   };
75   typedef std::vector<Element> Elements;
76   Elements container;
77
78 public:
79   /**
80    * Only allow const iteration over the dictionary
81    */
82   typedef typename Elements::const_iterator iterator;
83
84   /**
85    * Constructor
86    */
87   Dictionary<EntryType>()
88   {
89   }
90
91   /**
92    * Add a key value pair to the dictionary.
93    * If the entry does not already exist, add it to the dictionary
94    * using a shallow copy
95    */
96   bool Add( const std::string& name, const EntryType& entry )
97   {
98     for( typename Elements::iterator iter = container.begin(); iter != container.end(); ++iter )
99     {
100       if( iter->key == name )
101       {
102         return false;
103       }
104     }
105     container.push_back( Element(name, entry) );
106     return true;
107   }
108
109   /**
110    * Add a key-value pair to the dictionary
111    * If the entry does not already exist, add it to the dictionary
112    * (shallow copy)
113    */
114   bool Add( const char* name, const EntryType& entry )
115   {
116     bool result=false;
117     if( name != NULL )
118     {
119       std::string theName(name);
120       result=Add(theName, entry);
121     }
122     return result;
123   }
124
125   /**
126    * Remove a key value pair from the dictionary.
127    */
128   void Remove( const std::string& name )
129   {
130     for( typename Elements::iterator iter = container.begin(); iter != container.end(); ++iter )
131     {
132       if( iter->key == name )
133       {
134         container.erase( iter );
135         break;
136       }
137     }
138   }
139
140   /**
141    * Remove a key value pair from the dictionary.
142    */
143   void Remove( const char* name )
144   {
145     if( name != NULL )
146     {
147       std::string theName(name);
148       Remove(theName);
149     }
150   }
151
152   void Merge( const Dictionary<EntryType>& dictionary )
153   {
154     for( typename Elements::const_iterator fromIter = dictionary.container.begin(); fromIter != dictionary.container.end(); ++fromIter )
155     {
156       bool found=false;
157       for( typename Elements::iterator toIter = container.begin(); toIter != container.end(); ++toIter )
158       {
159         if( fromIter->key == toIter->key )
160         {
161           found=true;
162           toIter->entry = fromIter->entry;
163         }
164       }
165       if( !found )
166       {
167         container.push_back( Element(fromIter->key, fromIter->entry) );
168       }
169     }
170   }
171
172   /**
173    * Find the element in the dictionary pointed at by key, and
174    * insensitive search, and return a const pointer to it, or NULL
175    */
176   const EntryType* FindConst( const std::string& key ) const
177   {
178     if( ! key.empty() )
179     {
180       for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
181       {
182         if( Dali::CaseInsensitiveStringCompare(iter->key, key ))
183         {
184           const EntryType* result = &(iter->entry);
185           return result;
186         }
187       }
188     }
189     return NULL;
190   }
191
192   /**
193    * Find the element in the dictionary pointed at by key using a case
194    * insensitive search, and return a non-const pointer to it, or NULL
195    */
196   EntryType* Find( const std::string& key ) const
197   {
198     EntryType* result = NULL;
199     if( ! key.empty() )
200     {
201       for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
202       {
203         if( Dali::CaseInsensitiveStringCompare(iter->key, key ))
204         {
205           // Const cast because of const_iterator. const_iterator because, STL.
206           result = const_cast<EntryType*>(&(iter->entry));
207         }
208       }
209     }
210     return result;
211   }
212
213   /**
214    * Find the element in the dictionary pointed at by key using a case
215    * insensitive search, and return a const pointer to it, or NULL
216    */
217   const EntryType* FindConst( const char* key ) const
218   {
219     if( key != NULL )
220     {
221       std::string theKey(key);
222       return FindConst( theKey );
223     }
224     return NULL;
225   }
226
227   /**
228    * Find the element in the dictionary pointed at by key using a case
229    * insensitive search, and return a non-const pointer to it, or NULL
230    */
231   EntryType* Find( const char* key ) const
232   {
233     if( key != NULL )
234     {
235       std::string theKey(key);
236       return Find( theKey );
237     }
238     return NULL;
239   }
240   /**
241    * Return an iterator pointing at the first entry in the dictionary
242    */
243   typename Elements::const_iterator Begin() const
244   {
245     return container.begin();
246   }
247
248   /**
249    * Return an iterator pointing past the last entry in the dictionary
250    */
251   typename Elements::const_iterator End() const
252   {
253     return container.end();
254   }
255
256   void GetKeys( DictionaryKeys& keys ) const
257   {
258     keys.clear();
259     for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter )
260     {
261       keys.push_back( (*iter).key );
262     }
263   }
264
265   void Clear()
266   {
267     container.clear();
268   }
269 };
270
271
272
273 }//Internal
274 }//Toolkit
275 }//Dali
276
277 #endif // DALI_TOOLKIT_INTERNAL_BUILDER_DICTIONARY_H