svn update: 51457 (latest:51480)
[framework/uifw/eet.git] / src / lib / eet_dictionary.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <math.h>
8
9 #include <Eina.h>
10
11 #include "Eet.h"
12 #include "Eet_private.h"
13
14 Eet_Dictionary *
15 eet_dictionary_add(void)
16 {
17    Eet_Dictionary *new;
18
19    new = calloc(1, sizeof (Eet_Dictionary));
20    if (!new)
21       return NULL;
22
23    memset(new->hash, -1, sizeof (int) * 256);
24
25    return new;
26 } /* eet_dictionary_add */
27
28 void
29 eet_dictionary_free(Eet_Dictionary *ed)
30 {
31    if (ed)
32      {
33         int i;
34
35         for (i = 0; i < ed->count; ++i)
36            if (ed->all[i].str)
37               free(ed->all[i].str);
38
39         if (ed->all)
40            free(ed->all);
41
42         free(ed);
43      }
44 } /* eet_dictionary_free */
45
46 static int
47 _eet_dictionary_lookup(Eet_Dictionary *ed,
48                        const char     *string,
49                        int             hash)
50 {
51    int prev = -1;
52    int current;
53
54    current = ed->hash[hash];
55
56    while (current != -1)
57      {
58         if (ed->all[current].str)
59            if (strcmp(ed->all[current].str, string) >= 0)
60               break;
61
62         if (ed->all[current].mmap)
63            if (strcmp(ed->all[current].mmap, string) >= 0)
64               break;
65
66         prev = current;
67         current = ed->all[current].next;
68      }
69
70    if (current == -1)
71       return prev;
72
73    return current;
74 } /* _eet_dictionary_lookup */
75
76 int
77 eet_dictionary_string_add(Eet_Dictionary *ed,
78                           const char     *string)
79 {
80    Eet_String *current;
81    char *str;
82    int hash;
83    int idx;
84    int len;
85
86    if (!ed)
87       return -1;
88
89    hash = _eet_hash_gen(string, 8);
90
91    idx = _eet_dictionary_lookup(ed, string, hash);
92
93    if (idx != -1)
94      {
95         if (ed->all[idx].str)
96            if (strcmp(ed->all[idx].str, string) == 0)
97               return idx;
98
99         if (ed->all[idx].mmap)
100            if (strcmp(ed->all[idx].mmap, string) == 0)
101               return idx;
102
103      }
104
105    if (ed->total == ed->count)
106      {
107         Eet_String *new;
108         int total;
109
110         total = ed->total + 8;
111
112         new = realloc(ed->all, sizeof (Eet_String) * total);
113         if (new == NULL)
114            return -1;
115
116         ed->all = new;
117         ed->total = total;
118      }
119
120    len = strlen(string) + 1;
121    str = strdup(string);
122    if (str == NULL)
123       return -1;
124
125    current = ed->all + ed->count;
126
127    current->type = EET_D_NOT_CONVERTED;
128
129    current->hash = hash;
130
131    current->str = str;
132    current->len = len;
133    current->mmap = NULL;
134
135    if (idx == -1)
136      {
137         current->next = ed->hash[hash];
138         current->prev = -1;
139         ed->hash[hash] = ed->count;
140      }
141    else
142      {
143         current->next = idx;
144         current->prev = ed->all[idx].prev;
145
146         if (current->next != -1)
147            ed->all[current->next].prev = ed->count;
148
149         if (current->prev != -1)
150            ed->all[current->prev].next = ed->count;
151         else
152            ed->hash[hash] = ed->count;
153      }
154
155    return ed->count++;
156 } /* eet_dictionary_string_add */
157
158 int
159 eet_dictionary_string_get_size(const Eet_Dictionary *ed,
160                                int                   idx)
161 {
162    if (!ed)
163       return 0;
164
165    if (idx < 0)
166       return 0;
167
168    if (idx < ed->count)
169       return ed->all[idx].len;
170
171    return 0;
172 } /* eet_dictionary_string_get_size */
173
174 int
175 eet_dictionary_string_get_hash(const Eet_Dictionary *ed,
176                                int                   idx)
177 {
178    if (!ed)
179       return -1;
180
181    if (idx < 0)
182       return -1;
183
184    if (idx < ed->count)
185       return ed->all[idx].hash;
186
187    return -1;
188 } /* eet_dictionary_string_get_hash */
189
190 const char *
191 eet_dictionary_string_get_char(const Eet_Dictionary *ed,
192                                int                   idx)
193 {
194    if (!ed)
195       return NULL;
196
197    if (idx < 0)
198       return NULL;
199
200    if (idx < ed->count)
201      {
202 #ifdef _WIN32
203         /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */
204         if (ed->all[idx].str == NULL)
205           {
206              ed->all[idx].str = strdup(ed->all[idx].mmap);
207              ed->all[idx].mmap = NULL;
208           }
209
210 #else /* ifdef _WIN32 */
211         if (ed->all[idx].mmap)
212            return ed->all[idx].mmap;
213
214 #endif /* ifdef _WIN32 */
215         return ed->all[idx].str;
216      }
217
218    return NULL;
219 } /* eet_dictionary_string_get_char */
220
221 static inline Eina_Bool
222 _eet_dictionary_string_get_me_cache(const char *s,
223                                     int         len,
224                                     int        *mantisse,
225                                     int        *exponent)
226 {
227    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
228      {
229         *mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
230         *exponent = (s[5] - '0');
231
232         return EINA_TRUE;
233      }
234
235    return EINA_FALSE;
236 } /* _eet_dictionary_string_get_me_cache */
237
238 static inline Eina_Bool
239 _eet_dictionary_string_get_float_cache(const char *s,
240                                        int         len,
241                                        float      *result)
242 {
243    int mantisse;
244    int exponent;
245
246    if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent))
247      {
248         if (s[4] == '+')
249            *result = (float)(mantisse << exponent);
250         else
251            *result = (float)mantisse / (float)(1 << exponent);
252
253         return EINA_TRUE;
254      }
255
256    return EINA_FALSE;
257 } /* _eet_dictionary_string_get_float_cache */
258
259 static inline Eina_Bool
260 _eet_dictionary_string_get_double_cache(const char *s,
261                                         int         len,
262                                         double     *result)
263 {
264    int mantisse;
265    int exponent;
266
267    if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent))
268      {
269         if (s[4] == '+')
270            *result = (double)(mantisse << exponent);
271         else
272            *result = (double)mantisse / (float)(1 << exponent);
273
274         return EINA_TRUE;
275      }
276
277    return EINA_FALSE;
278 } /* _eet_dictionary_string_get_double_cache */
279
280 static inline Eina_Bool
281 _eet_dictionary_test(const Eet_Dictionary *ed,
282                      int                   idx,
283                      void                 *result)
284 {
285    if (!result)
286       return EINA_FALSE;
287
288    if (!ed)
289       return EINA_FALSE;
290
291    if (idx < 0)
292       return EINA_FALSE;
293
294    if (!(idx < ed->count))
295       return EINA_FALSE;
296
297    return EINA_TRUE;
298 } /* _eet_dictionary_test */
299
300 Eina_Bool
301 eet_dictionary_string_get_float(const Eet_Dictionary *ed,
302                                 int                   idx,
303                                 float                *result)
304 {
305    if (!_eet_dictionary_test(ed, idx, result))
306       return EINA_FALSE;
307
308    if (!(ed->all[idx].type & EET_D_FLOAT))
309      {
310         const char *str;
311
312         str = ed->all[idx].str ? ed->all[idx].str : ed->all[idx].mmap;
313
314         if (!_eet_dictionary_string_get_float_cache(str, ed->all[idx].len,
315                                                     &ed->all[idx].f))
316           {
317              long long mantisse = 0;
318              long exponent = 0;
319
320              if (eina_convert_atod(str, ed->all[idx].len, &mantisse,
321                                    &exponent) == EINA_FALSE)
322                 return EINA_FALSE;
323
324              ed->all[idx].f = ldexpf((float)mantisse, exponent);
325           }
326
327         ed->all[idx].type |= EET_D_FLOAT;
328      }
329
330    *result = ed->all[idx].f;
331    return EINA_TRUE;
332 } /* eet_dictionary_string_get_float */
333
334 Eina_Bool
335 eet_dictionary_string_get_double(const Eet_Dictionary *ed,
336                                  int                   idx,
337                                  double               *result)
338 {
339    if (!_eet_dictionary_test(ed, idx, result))
340       return EINA_FALSE;
341
342    if (!(ed->all[idx].type & EET_D_DOUBLE))
343      {
344         const char *str;
345
346         str = ed->all[idx].str ? ed->all[idx].str : ed->all[idx].mmap;
347
348         if (!_eet_dictionary_string_get_double_cache(str, ed->all[idx].len,
349                                                      &ed->all[idx].d))
350           {
351              long long mantisse = 0;
352              long exponent = 0;
353
354              if (eina_convert_atod(str, ed->all[idx].len, &mantisse,
355                                    &exponent) == EINA_FALSE)
356                 return EINA_FALSE;
357
358              ed->all[idx].d = ldexp((double)mantisse, exponent);
359           }
360
361         ed->all[idx].type |= EET_D_DOUBLE;
362      }
363
364    *result = ed->all[idx].d;
365    return EINA_TRUE;
366 } /* eet_dictionary_string_get_double */
367
368 Eina_Bool
369 eet_dictionary_string_get_fp(const Eet_Dictionary *ed,
370                              int                   idx,
371                              Eina_F32p32          *result)
372 {
373    if (!_eet_dictionary_test(ed, idx, result))
374       return EINA_FALSE;
375
376    if (!(ed->all[idx].type & EET_D_FIXED_POINT))
377      {
378         const char *str;
379         Eina_F32p32 fp;
380
381         str = ed->all[idx].str ? ed->all[idx].str : ed->all[idx].mmap;
382
383         if (!eina_convert_atofp(str, ed->all[idx].len, &fp))
384            return EINA_FALSE;
385
386         ed->all[idx].fp = fp;
387         ed->all[idx].type |= EET_D_FIXED_POINT;
388      }
389
390    *result = ed->all[idx].fp;
391    return EINA_TRUE;
392 } /* eet_dictionary_string_get_fp */
393
394 EAPI int
395 eet_dictionary_string_check(Eet_Dictionary *ed,
396                             const char     *string)
397 {
398    int i;
399
400    if ((ed == NULL) || (string == NULL))
401       return 0;
402
403    if ((ed->start <= string) && (string < ed->end))
404       return 1;
405
406    for (i = 0; i < ed->count; ++i)
407       if (ed->all[i].str == string)
408          return 1;
409
410    return 0;
411 } /* eet_dictionary_string_check */
412