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