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