#ifdef HAVE_CONFIG_H # include #endif /* ifdef HAVE_CONFIG_H */ #include #include #include #include #include "Eet.h" #include "Eet_private.h" Eet_Dictionary * eet_dictionary_add(void) { Eet_Dictionary *new; new = eet_dictionary_calloc(1); if (!new) return NULL; memset(new->hash, -1, sizeof (int) * 256); return new; } void eet_dictionary_free(Eet_Dictionary *ed) { int i; if (!ed) return; for (i = 0; i < ed->count; ++i) if (ed->all[i].allocated) eina_stringshare_del(ed->all[i].str); if (ed->all) free(ed->all); if (ed->converts) eina_hash_free(ed->converts); eet_dictionary_mp_free(ed); } static int _eet_dictionary_lookup(Eet_Dictionary *ed, const char *string, int len, int hash) { Eina_Bool found = EINA_FALSE; int prev = -1; int current; current = ed->hash[hash]; while (current != -1) { if (ed->all[current].len == len) { if (ed->all[current].str && (ed->all[current].str == string || strcmp(ed->all[current].str, string) == 0)) { found = EINA_TRUE; break; } } prev = current; current = ed->all[current].next; } if (current == -1 && found) return prev; return current; } int eet_dictionary_string_add(Eet_Dictionary *ed, const char *string) { Eet_String *current; const char *str; int hash; int idx; int len; if (!ed) return -1; hash = _eet_hash_gen(string, 8); len = strlen(string) + 1; idx = _eet_dictionary_lookup(ed, string, len, hash); if (idx != -1) { if (ed->all[idx].str && (ed->all[idx].str == string || strcmp(ed->all[idx].str, string) == 0)) return idx; } if (ed->total == ed->count) { Eet_String *new; int total; total = ed->total + 8; new = realloc(ed->all, total * sizeof(Eet_String)); if (!new) return -1; ed->all = new; ed->total = total; } str = eina_stringshare_add(string); if (!str) return -1; current = ed->all + ed->count; current->allocated = EINA_TRUE; current->hash = hash; current->str = str; current->len = len; if (idx == -1) { current->next = ed->hash[hash]; current->prev = -1; ed->hash[hash] = ed->count; } else { current->next = idx; current->prev = ed->all[idx].prev; if (current->next != -1) ed->all[current->next].prev = ed->count; if (current->prev != -1) ed->all[current->prev].next = ed->count; else ed->hash[hash] = ed->count; } return ed->count++; } int eet_dictionary_string_get_size(const Eet_Dictionary *ed, int idx) { if (!ed) return 0; if (idx < 0) return 0; if (idx < ed->count) return ed->all[idx].len; return 0; } EAPI int eet_dictionary_count(const Eet_Dictionary *ed) { return ed->count; } int eet_dictionary_string_get_hash(const Eet_Dictionary *ed, int idx) { if (!ed) return -1; if (idx < 0) return -1; if (idx < ed->count) return ed->all[idx].hash; return -1; } const char * eet_dictionary_string_get_char(const Eet_Dictionary *ed, int idx) { if (!ed) return NULL; if (idx < 0) return NULL; if (idx < ed->count) { #ifdef _WIN32 /* Windows file system could change the mmaped file when replacing a file. So we need to copy all string in memory to avoid bugs. */ if (!ed->all[idx].allocated) { ed->all[idx].str = eina_stringshare_add(ed->all[idx].str); ed->all[idx].allocated = EINA_TRUE; } #endif /* ifdef _WIN32 */ return ed->all[idx].str; } return NULL; } static inline Eina_Bool _eet_dictionary_string_get_me_cache(const char *s, int len, int *mantisse, int *exponent) { if ((len == 6) && (s[0] == '0') && (s[1] == 'x') && (s[3] == 'p')) { *mantisse = (s[2] >= 'a') ? (s[2] - 'a' + 10) : (s[2] - '0'); *exponent = (s[5] - '0'); return EINA_TRUE; } return EINA_FALSE; } static inline Eina_Bool _eet_dictionary_string_get_float_cache(const char *s, int len, float *result) { int mantisse; int exponent; if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) { if (s[4] == '+') *result = (float)(mantisse << exponent); else *result = (float)mantisse / (float)(1 << exponent); return EINA_TRUE; } return EINA_FALSE; } static inline Eina_Bool _eet_dictionary_string_get_double_cache(const char *s, int len, double *result) { int mantisse; int exponent; if (_eet_dictionary_string_get_me_cache(s, len, &mantisse, &exponent)) { if (s[4] == '+') *result = (double)(mantisse << exponent); else *result = (double)mantisse / (float)(1 << exponent); return EINA_TRUE; } return EINA_FALSE; } static inline Eina_Bool _eet_dictionary_test(const Eet_Dictionary *ed, int idx, void *result) { if (!result) return EINA_FALSE; if (!ed) return EINA_FALSE; if (idx < 0) return EINA_FALSE; if (!(idx < ed->count)) return EINA_FALSE; return EINA_TRUE; } static Eet_Convert * eet_dictionary_convert_get(const Eet_Dictionary *ed, int idx, const char **str) { Eet_Convert *result; *str = ed->all[idx].str; if (!ed->converts) { ((Eet_Dictionary *)ed)->converts = eina_hash_int32_new(free); goto add_convert; } result = eina_hash_find(ed->converts, &idx); if (result) return result; add_convert: result = calloc(1, sizeof (Eet_Convert)); eina_hash_add(ed->converts, &idx, result); return result; } Eina_Bool eet_dictionary_string_get_float(const Eet_Dictionary *ed, int idx, float *result) { Eet_Convert *convert; const char *str; if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE; convert = eet_dictionary_convert_get(ed, idx, &str); if (!convert) return EINA_FALSE; if (!(convert->type & EET_D_FLOAT)) { if (!_eet_dictionary_string_get_float_cache(str, ed->all[idx].len, &convert->f)) { long long mantisse = 0; long exponent = 0; if (eina_convert_atod(str, ed->all[idx].len, &mantisse, &exponent) == EINA_FALSE) return EINA_FALSE; convert->f = ldexpf((float)mantisse, exponent); } convert->type |= EET_D_FLOAT; } *result = convert->f; return EINA_TRUE; } Eina_Bool eet_dictionary_string_get_double(const Eet_Dictionary *ed, int idx, double *result) { Eet_Convert *convert; const char *str; if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE; convert = eet_dictionary_convert_get(ed, idx, &str); if (!convert) return EINA_FALSE; if (!(convert->type & EET_D_DOUBLE)) { if (!_eet_dictionary_string_get_double_cache(str, ed->all[idx].len, &convert->d)) { long long mantisse = 0; long exponent = 0; if (eina_convert_atod(str, ed->all[idx].len, &mantisse, &exponent) == EINA_FALSE) return EINA_FALSE; convert->d = ldexp((double)mantisse, exponent); } convert->type |= EET_D_DOUBLE; } *result = convert->d; return EINA_TRUE; } Eina_Bool eet_dictionary_string_get_fp(const Eet_Dictionary *ed, int idx, Eina_F32p32 *result) { Eet_Convert *convert; const char *str; if (!_eet_dictionary_test(ed, idx, result)) return EINA_FALSE; convert = eet_dictionary_convert_get(ed, idx, &str); if (!convert) return EINA_FALSE; if (!(convert->type & EET_D_FIXED_POINT)) { Eina_F32p32 fp; if (!eina_convert_atofp(str, ed->all[idx].len, &fp)) return EINA_FALSE; convert->fp = fp; convert->type |= EET_D_FIXED_POINT; } *result = convert->fp; return EINA_TRUE; } EAPI int eet_dictionary_string_check(Eet_Dictionary *ed, const char *string) { int i; if ((!ed) || (!string)) return 0; if ((ed->start <= string) && (string < ed->end)) return 1; for (i = 0; i < ed->count; ++i) if ((ed->all[i].allocated) && ed->all[i].str == string) return 1; return 0; }