Tail * tail_read (FILE *file) { long save_pos; Tail *t; TrieIndex i; uint32 sig; /* check signature */ save_pos = ftell (file); if (!file_read_int32 (file, (int32 *) &sig) || TAIL_SIGNATURE != sig) goto exit_file_read; if (NULL == (t = (Tail *) malloc (sizeof (Tail)))) goto exit_file_read; if (!file_read_int32 (file, &t->first_free) || !file_read_int32 (file, &t->num_tails)) { goto exit_tail_created; } if (t->num_tails > SIZE_MAX / sizeof (TailBlock)) goto exit_tail_created; t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock)); if (!t->tails) goto exit_tail_created; for (i = 0; i < t->num_tails; i++) { int16 length; if (!file_read_int32 (file, &t->tails[i].next_free) || !file_read_int32 (file, &t->tails[i].data) || !file_read_int16 (file, &length)) { goto exit_in_loop; } t->tails[i].suffix = (TrieChar *) malloc (length + 1); if (length > 0) { if (!file_read_chars (file, (char *)t->tails[i].suffix, length)) { free (t->tails[i].suffix); goto exit_in_loop; } } t->tails[i].suffix[length] = '\0'; } return t; exit_in_loop: while (i > 0) { free (t->tails[--i].suffix); } free (t->tails); exit_tail_created: free (t); exit_file_read: fseek (file, save_pos, SEEK_SET); return NULL; }
Tail * tail_open (const char *path, const char *name, TrieIOMode mode) { Tail *t; TrieIndex i; uint16 sig; long file_size; t = (Tail *) malloc (sizeof (Tail)); t->file = file_open (path, name, ".tl", mode); if (!t->file) goto exit1; file_size = file_length (t->file); if (file_size != 0 && file_read_int16 (t->file, (int16 *) &sig) && sig != TAIL_SIGNATURE) { goto exit2; } /* init tails data */ if (file_size == 0) { t->first_free = 0; t->num_tails = 0; t->tails = NULL; t->is_dirty = TRUE; } else { file_read_int16 (t->file, &t->first_free); file_read_int16 (t->file, &t->num_tails); t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock)); if (!t->tails) goto exit2; for (i = 0; i < t->num_tails; i++) { int8 length; file_read_int16 (t->file, &t->tails[i].next_free); file_read_int16 (t->file, &t->tails[i].data); file_read_int8 (t->file, &length); t->tails[i].suffix = (TrieChar *) malloc (length + 1); if (length > 0) file_read_chars (t->file, (char *)t->tails[i].suffix, length); t->tails[i].suffix[length] = '\0'; } t->is_dirty = FALSE; } return t; exit2: fclose (t->file); exit1: free (t); return NULL; }
static bool address_expansion_read(FILE *f, address_expansion_t *expansion) { if (f == NULL) return false; if (!file_read_uint32(f, (uint32_t *)&expansion->canonical_index)) { return false; } uint32_t language_len; if (!file_read_uint32(f, &language_len)) { return false; } if (!file_read_chars(f, expansion->language, language_len)) { return false; } if (!file_read_uint32(f, (uint32_t *)&expansion->num_dictionaries)) { return false; } for (size_t i = 0; i < expansion->num_dictionaries; i++) { if (!file_read_uint16(f, (uint16_t *)expansion->dictionary_ids + i)) { return false; } } if (!file_read_uint32(f, &expansion->address_components)) { return false; } if (!file_read_uint8(f, (uint8_t *)&expansion->separable)) { return false; } return true; }
geodb_t *geodb_init(char *dir) { if (dir == NULL) return NULL; geodb_t *gdb = malloc(sizeof(geodb_t)); if (gdb == NULL) return NULL; char_array *path = char_array_new_size(strlen(dir)); char_array_cat_joined(path, PATH_SEPARATOR, true, 2, dir, GEODB_NAMES_TRIE_FILENAME); char *names_path = char_array_get_string(path); gdb->names = trie_load(names_path); if (gdb->names == NULL) { goto exit_geodb_created; } char_array_clear(path); char_array_cat_joined(path, PATH_SEPARATOR, true, 2, dir, GEODB_FEATURES_TRIE_FILENAME); char *features_path = char_array_get_string(path); gdb->features = trie_load(features_path); if(gdb->features == NULL) { goto exit_geodb_created; } char_array_clear(path); char_array_cat_joined(path, PATH_SEPARATOR, true, 2, dir, GEODB_POSTAL_CODES_FILENAME); char *postal_codes_path = char_array_get_string(path); FILE *f = fopen(postal_codes_path, "rb"); uint64_t num_postal_strings = 0; if (!file_read_uint64(f, (uint64_t *)&num_postal_strings)) { goto exit_geodb_created; } size_t postal_codes_str_len; if (!file_read_uint64(f, (uint64_t *)&postal_codes_str_len)) { goto exit_geodb_created; } char_array *array = char_array_new_size(postal_codes_str_len); if (!file_read_chars(f, array->a, postal_codes_str_len)) { goto exit_geodb_created; } array->n = postal_codes_str_len; gdb->postal_codes = cstring_array_from_char_array(array); if (cstring_array_num_strings(gdb->postal_codes) != num_postal_strings) { goto exit_geodb_created; } fclose(f); char_array_clear(path); char_array_cat_joined(path, PATH_SEPARATOR, true, 2, dir, GEODB_HASH_FILENAME); char *hash_file_path = strdup(char_array_get_string(path)); char_array_clear(path); char_array_cat_joined(path, PATH_SEPARATOR, true, 2, dir, GEODB_LOG_FILENAME); char *log_path = char_array_get_string(path); gdb->hash_reader = NULL; if ((sparkey_hash_open(&gdb->hash_reader, hash_file_path, log_path)) != SPARKEY_SUCCESS) { free(hash_file_path); char_array_destroy(path); goto exit_geodb_created; } free(hash_file_path); char_array_destroy(path); gdb->log_iter = NULL; if ((sparkey_logiter_create(&gdb->log_iter, sparkey_hash_getreader(gdb->hash_reader))) != SPARKEY_SUCCESS) { goto exit_geodb_created; } gdb->value_buf = char_array_new_size(sparkey_logreader_maxvaluelen(sparkey_hash_getreader(gdb->hash_reader))); if (gdb->value_buf == NULL) { goto exit_geodb_created; } gdb->geoname = geoname_new(); if (gdb->geoname == NULL) { goto exit_geodb_created; } gdb->postal_code = gn_postal_code_new(); if (gdb->postal_code == NULL) { goto exit_geodb_created; } return gdb; exit_geodb_created: geodb_destroy(gdb); return NULL; }
bool address_dictionary_read(FILE *f) { if (address_dict != NULL) return false; uint32_t signature; if (!file_read_uint32(f, &signature) || signature != ADDRESS_DICTIONARY_SIGNATURE) { return false; } address_dict = malloc(sizeof(address_dictionary_t)); if (address_dict == NULL) return false; uint32_t canonical_str_len; if (!file_read_uint32(f, &canonical_str_len)) { goto exit_address_dict_created; } char_array *array = char_array_new_size(canonical_str_len); if (array == NULL) { goto exit_address_dict_created; } if (!file_read_chars(f, array->a, canonical_str_len)) { char_array_destroy(array); goto exit_address_dict_created; } array->n = canonical_str_len; address_dict->canonical = cstring_array_from_char_array(array); uint32_t num_values; if (!file_read_uint32(f, &num_values)) { goto exit_address_dict_created; } address_dict->values = address_expansion_value_array_new_size(num_values); for (uint32_t i = 0; i < num_values; i++) { address_expansion_value_t *value = address_expansion_value_read(f); if (value == NULL) { goto exit_address_dict_created; } address_expansion_value_array_push(address_dict->values, value); } address_dict->trie = trie_read(f); if (address_dict->trie == NULL) { goto exit_address_dict_created; } return true; exit_address_dict_created: address_dictionary_destroy(address_dict); return false; }