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