src/server/ucx/map.c

changeset 36
450d2d5f4735
parent 31
280250e45ba6
child 66
74babc0082b7
--- 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;
+}

mercurial