Use eina conversion functions (Remove code from eet).
[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
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 }
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         if (ed->all) free(ed->all);
43         free(ed);
44      }
45 }
46
47 static int
48 _eet_dictionary_lookup(Eet_Dictionary *ed, const char *string, int hash)
49 {
50    int  prev = -1;
51    int  current;
52
53    current = ed->hash[hash];
54
55    while (current != -1)
56      {
57         if (ed->all[current].str)
58           {
59              if (strcmp(ed->all[current].str, string) >= 0)
60                break ;
61           }
62         if (ed->all[current].mmap)
63           {
64              if (strcmp(ed->all[current].mmap, string) >= 0)
65                break ;
66           }
67
68         prev = current;
69         current = ed->all[current].next;
70      }
71
72    if (current == -1)
73      return prev;
74
75    return current;
76 }
77
78 int
79 eet_dictionary_string_add(Eet_Dictionary *ed, const char *string)
80 {
81    Eet_String   *current;
82    char         *str;
83    int           hash;
84    int           index;
85    int           len;
86
87    if (!ed)
88      return -1;
89
90    hash = _eet_hash_gen(string, 8);
91
92    index = _eet_dictionary_lookup(ed, string, hash);
93
94    if (index != -1)
95      {
96         if (ed->all[index].str)
97           {
98              if (strcmp(ed->all[index].str, string) == 0)
99                return index;
100           }
101         if (ed->all[index].mmap)
102           {
103              if (strcmp(ed->all[index].mmap, string) == 0)
104                return index;
105           }
106      }
107
108    if (ed->total == ed->count)
109      {
110         Eet_String      *new;
111         int              total;
112
113         total = ed->total + 8;
114
115         new = realloc(ed->all, sizeof (Eet_String) * total);
116         if (new == NULL)
117           return -1;
118
119         ed->all = new;
120         ed->total = total;
121      }
122
123    len = strlen(string) + 1;
124    str = strdup(string);
125    if (str == NULL)
126      return -1;
127
128    current = ed->all + ed->count;
129
130    current->flags.converted = 0;
131    current->flags.is_float = 0;
132
133    current->hash = hash;
134
135    current->str = str;
136    current->len = len;
137    current->mmap = NULL;
138
139    if (index == -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 = index;
148         current->prev = ed->all[index].prev;
149
150         if (current->next != -1)
151           ed->all[current->next].prev = ed->count;
152         if (current->prev != -1)
153           ed->all[current->prev].next = ed->count;
154         else
155           ed->hash[hash] = ed->count;
156      }
157
158    return ed->count++;
159 }
160
161 int
162 eet_dictionary_string_get_size(const Eet_Dictionary *ed, int index)
163 {
164    if (!ed) return 0;
165    if (index < 0) return 0;
166    if (index < ed->count)
167      return ed->all[index].len;
168    return 0;
169 }
170
171 int
172 eet_dictionary_string_get_hash(const Eet_Dictionary *ed, int index)
173 {
174    if (!ed) return -1;
175    if (index < 0) return -1;
176    if (index < ed->count)
177      return ed->all[index].hash;
178    return -1;
179 }
180
181 const char *
182 eet_dictionary_string_get_char(const Eet_Dictionary *ed, int index)
183 {
184    if (!ed) return NULL;
185    if (index < 0) return NULL;
186    if (index < ed->count)
187      {
188 #ifdef _WIN32
189         /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */
190         if (ed->all[index].str == NULL)
191           {
192              ed->all[index].str = strdup(ed->all[index].mmap);
193              ed->all[index].mmap = NULL;
194           }
195 #else
196         if (ed->all[index].mmap)
197           return ed->all[index].mmap;
198 #endif
199         return ed->all[index].str;
200      }
201    return NULL;
202 }
203
204 static inline int
205 _eet_dictionary_string_get_me_cache(const char *s, int len, int *mantisse, int *exponent)
206 {
207    if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p'))
208      {
209         *mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0');
210         *exponent = (s[5] - '0');
211
212         return -1;
213      }
214    return 0;
215 }
216
217 static inline int
218 _eet_dictionary_string_get_float_cache(const char *s, int len, float *result)
219 {
220    int  mantisse;
221    int  exponent;
222
223    if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent))
224      {
225         if (s[4] == '+')        *result = (float) (mantisse << exponent);
226         else                    *result = (float) mantisse / (float) (1 << exponent);
227
228         return -1;
229      }
230    return 0;
231 }
232
233 static inline int
234 _eet_dictionary_string_get_double_cache(const char *s, int len, double *result)
235 {
236    int  mantisse;
237    int  exponent;
238
239    if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent))
240      {
241         if (s[4] == '+')        *result = (double) (mantisse << exponent);
242         else                    *result = (double) mantisse / (float) (1 << exponent);
243
244         return -1;
245      }
246    return 0;
247 }
248
249 int
250 eet_dictionary_string_get_float(const Eet_Dictionary *ed, int index, float *result)
251 {
252    if (!result) return 0;
253    if (!ed) return 0;
254    if (index < 0) return 0;
255    if (index < ed->count)
256      {
257         if (!(ed->all[index].flags.converted
258               && ed->all[index].flags.is_float))
259           {
260              const char      *str;
261
262              str = ed->all[index].str ? ed->all[index].str : ed->all[index].mmap;
263
264              if (!_eet_dictionary_string_get_float_cache(str, ed->all[index].len, &ed->all[index].convert.f))
265                {
266                   long long    mantisse = 0;
267                   long         exponent = 0;
268
269                   if (eina_convert_atod(str, ed->all[index].len, &mantisse, &exponent) == EINA_FALSE)
270                     return 0;
271
272                   ed->all[index].convert.f = ldexpf((float) mantisse, exponent);
273                }
274
275              ed->all[index].flags.is_float = 1;
276           }
277
278         *result = ed->all[index].convert.f;
279         return -1;
280      }
281    return 0;
282 }
283
284 int
285 eet_dictionary_string_get_double(const Eet_Dictionary *ed, int index, double *result)
286 {
287    if (!result) return 0;
288    if (!ed) return 0;
289    if (index < 0) return 0;
290    if (index < ed->count)
291      {
292         if (!(ed->all[index].flags.converted
293               && !ed->all[index].flags.is_float))
294           {
295              const char      *str;
296
297              str = ed->all[index].str ? ed->all[index].str : ed->all[index].mmap;
298
299              if (!_eet_dictionary_string_get_double_cache(str, ed->all[index].len, &ed->all[index].convert.d))
300                {
301                   long long    mantisse = 0;
302                   long         exponent = 0;
303
304                   if (eina_convert_atod(str, ed->all[index].len, &mantisse, &exponent) == EINA_FALSE)
305                     return 0;
306
307                   ed->all[index].convert.d = ldexp((double) mantisse, exponent);
308                }
309
310              ed->all[index].flags.is_float = 0;
311           }
312
313         *result = ed->all[index].convert.d;
314         return -1;
315      }
316    return 0;
317 }
318
319 EAPI int
320 eet_dictionary_string_check(Eet_Dictionary *ed, const char *string)
321 {
322    int  i;
323
324    if (ed == NULL
325        || string == NULL)
326      return 0;
327
328    if (ed->start <= string
329        && string < ed->end)
330      return 1;
331
332    for (i = 0; i < ed->count; ++i)
333      if (ed->all[i].str == string)
334        return 1;
335
336    return 0;
337 }