--- a/src/server/ucx/map.c Sat Aug 18 11:39:34 2012 +0200 +++ b/src/server/ucx/map.c Sat Oct 06 13:00:07 2012 +0200 @@ -8,6 +8,10 @@ #include "map.h" UcxMap *ucx_map_new(size_t size) { + if(size == 0) { + size = 16; + } + UcxMap *map = (UcxMap*)malloc(sizeof(UcxMap)); if(map == NULL) { return NULL; @@ -19,6 +23,7 @@ return NULL; } map->size = size; + map->count = 0; return map; } @@ -39,6 +44,48 @@ free(map); } +int ucx_map_copy(UcxMap *from, UcxMap *to, copy_func fnc, void *data) { + UcxMapIterator i = ucx_map_iterator(from); + void *value; + UCX_MAP_FOREACH(value, i) { + int ret = ucx_map_put(to, i.cur->key, fnc ? fnc(value, data) : value); + if(ret != 0) { + return 1; + } + } + return 0; +} + +UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data) { + size_t bs = (map->count * 5) >> 1; + UcxMap *newmap = ucx_map_new(bs > map->size ? bs : map->size); + if(newmap == NULL) { + return NULL; + } + ucx_map_copy(map, newmap, fnc, data); + return newmap; +} + +int ucx_map_rehash(UcxMap *map) { + size_t load = (map->size * 3) >> 2; + if (map->count > load) { + UcxMap oldmap; + oldmap.map = map->map; + oldmap.size = map->size; + oldmap.count = map->count; + + map->size = (map->count * 5) >> 1; + map->map = (UcxMapElement**)calloc(map->size, sizeof(UcxMapElement*)); + if(map->map == NULL) { + *map = oldmap; + return 1; + } + map->count = 0; + ucx_map_copy(&oldmap, map, NULL, NULL); + } + return 0; +} + int ucx_map_put(UcxMap *map, UcxKey key, void *data) { if(key.hash == 0) { key.hash = ucx_hash((char*)key.data, key.len); @@ -76,6 +123,7 @@ memcpy(kd, key.data, key.len); key.data = kd; elm->key = key; + map->count++; } elm->data = data; @@ -138,8 +186,11 @@ switch (len) { case 3: h ^= (data[i + 2] & 0xFF) << 16; + /* no break */ case 2: h ^= (data[i + 1] & 0xFF) << 8; + /* no break */ case 1: h ^= (data[i + 0] & 0xFF); h *= m; + /* no break */ } h ^= h >> 13; @@ -186,3 +237,124 @@ return 1; } + +int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator, + ucx_map_coder decoder, void* decdata) { + + int c; int r, n; + + char *key, *value; + + while ((c = fgetc(f)) > 0) { + /* Discard leading spaces and comments */ + if (c < 33) continue; + if (c == '#' || c == '!') { + while ((c = (char) fgetc(f)) > 0) { + if (c == '\n') break; + } + continue; + } + + /* read into key buffer */ + n = 16; + key = malloc(n); + r = 0; + do { + if (c == '=') break; + if (r > n - 2) { + n *= 2; + key = realloc(key, n); + } + key[r] = c; + r++; + } while ((c = fgetc(f)) > 0); + if (c <= 0) { + free(key); + return 1; + } + key[r] = 0; + while (key[--r] == ' ') key[r] = 0; + + /* skip whitespaces */ + while ((c = fgetc(f)) > 0) { + if (c > 32) break; + } + if (c <= 0) { + free(key); + return 1; + } + + /* read into value buffer */ + n = 64; + value = malloc(n); + r = 0; + do { + if (c == '\n') break; + if (r > n - 2) { + n *= 2; + value = realloc(value, n); + } + value[r] = c; + r++; + } while ((c = fgetc(f)) > 0); + value[r] = 0; + while (value[--r] < 33) value[r] = 0; + + if (decoder) { + size_t decodedSize; + void *decoded = decoder(value, decdata, &decodedSize); + free(value); + value = decoded; + r = decodedSize; + } else { + r += 2; + value = realloc(value, r); + } + + if (allocator.pool) { + void *pooledValue = allocator.malloc(allocator.pool, r); + memcpy(pooledValue, value, r); + free(value); + value = pooledValue; + } + + ucx_map_cstr_put(map, key, value); + free(key); + } + + return 0; +} + +int ucx_map_store_enc(UcxMap *map, FILE *f, + ucx_map_coder encoder, void *encdata) { + UcxMapIterator iter = ucx_map_iterator(map); + char *k, *v; + sstr_t key, value; + int written; + + UCX_MAP_FOREACH(v, iter) { + k = (char*) iter.cur->key.data; + key = sstr(k); + if (encoder) { + size_t encodedSize; + void *encoded = encoder(v, encdata, &encodedSize); + value = sstrn(encoded,encodedSize - 1); + } else { + value = sstr(v); + } + + written = 0; + written += fwrite(key.ptr, 1, key.length, f); + written += fwrite(" = ", 1, 3, f); + written += fwrite(value.ptr, 1, value.length, f); + written += fwrite("\n", 1, 1, f); + + if (encoder) { + free(value.ptr); + } + + if (written != key.length + value.length + 4) return 1; + } + + return 0; +}