map can now load values from file into pooled memory

Fri, 05 Oct 2012 11:52:53 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 05 Oct 2012 11:52:53 +0200
changeset 48
621a4430c404
parent 46
48ca036d7d9c
child 49
1771360b740d

map can now load values from file into pooled memory

use with care when using a decoder that also allocates memory

test/main.c file | annotate | diff | comparison | revisions
test/map_tests.c file | annotate | diff | comparison | revisions
test/map_tests.h file | annotate | diff | comparison | revisions
ucx/map.c file | annotate | diff | comparison | revisions
ucx/map.h file | annotate | diff | comparison | revisions
ucx/mempool.c file | annotate | diff | comparison | revisions
ucx/mempool.h file | annotate | diff | comparison | revisions
--- a/test/main.c	Fri Oct 05 10:25:33 2012 +0200
+++ b/test/main.c	Fri Oct 05 11:52:53 2012 +0200
@@ -148,6 +148,7 @@
         ucx_test_register(suite, test_ucx_map_iterator);
         ucx_test_register(suite, test_ucx_map_iterator_chain);
         ucx_test_register(suite, test_ucx_map_store_load);
+        ucx_test_register(suite, test_ucx_map_store_load_with_mempool);
         ucx_test_register(suite, test_ucx_map_clone);
         
         /* sstring Tests */
--- a/test/map_tests.c	Fri Oct 05 10:25:33 2012 +0200
+++ b/test/map_tests.c	Fri Oct 05 11:52:53 2012 +0200
@@ -141,7 +141,7 @@
     ucx_map_free(map);
 }
 
-void* test_ucx_map_store_load_encdec(void *value, void *data) {
+void* test_ucx_map_store_load_encdec(void *value, void *data, size_t *size) {
     char *string = (char*) value;
     size_t n = strlen(string);
     char *encoded = malloc(n+1);
@@ -149,6 +149,7 @@
         encoded[i] = string[n-1-i];
     }
     encoded[n] = 0;
+    *size = n+1;
     return encoded;
 }
 
@@ -173,7 +174,11 @@
     ucx_map_free(map);
     map = ucx_map_new(1);
     f = fopen("test_ucx_map_store", "r");
-    r += ucx_map_load_enc(map, f, test_ucx_map_store_load_encdec, NULL);
+    UcxAllocator allocator = UCX_ALLOCATOR_DEFAULT;
+    r += ucx_map_load_enc(map, f, allocator,
+            test_ucx_map_store_load_encdec, NULL);
+    fclose(f);
+    unlink("test_ucx_map_store");
 
     UCX_TEST_BEGIN
     char *value;
@@ -205,9 +210,43 @@
             "value error for key: simple");
 
     UCX_TEST_END
+}
+
+UCX_TEST_IMPLEMENT(test_ucx_map_store_load_with_mempool) {
+    UcxMap *map = ucx_map_new(4);
+
+    ucx_map_cstr_put(map, "test", "test");
+    ucx_map_cstr_put(map, "key", "value");
+    ucx_map_cstr_put(map, "testkey", "testvalue");
+    ucx_map_cstr_put(map, "simple", "a simple value");
+
+    FILE *f = fopen("test_ucx_map_store", "w");
+    int r;
+    r = ucx_map_store_enc(map, f, NULL, NULL);
     fclose(f);
+    ucx_map_free(map);
 
+    UcxMempool *pool = ucx_mempool_new(4);
+    map = ucx_map_new(4);
+    f = fopen("test_ucx_map_store", "r");
+    UcxAllocator allocator = UCX_ALLOCATOR_MEMPOOL(pool);
+    r += ucx_map_load_enc(map, f, allocator,
+            test_ucx_map_store_load_encdec, NULL);
+    fclose(f);
     unlink("test_ucx_map_store");
+
+    UCX_TEST_BEGIN
+    UCX_TEST_ASSERT(r == 0, "IO errors, test cannot be performed");
+    UcxMapIterator iter = ucx_map_iterator(map);
+    char *value; size_t n;
+    UCX_MAP_FOREACH(value, iter) {
+        n = strlen(value);
+        UCX_TEST_ASSERT(strncmp(pool->data[iter.index], value, n),
+                "values of map does not match pooled values");
+    }
+    UCX_TEST_END
+
+    ucx_mempool_free(pool);
 }
 
 UCX_TEST_IMPLEMENT(test_ucx_map_clone) {
--- a/test/map_tests.h	Fri Oct 05 10:25:33 2012 +0200
+++ b/test/map_tests.h	Fri Oct 05 11:52:53 2012 +0200
@@ -19,6 +19,7 @@
 UCX_TEST_DECLARE(test_ucx_map_iterator)
 UCX_TEST_DECLARE(test_ucx_map_iterator_chain)
 UCX_TEST_DECLARE(test_ucx_map_store_load)
+UCX_TEST_DECLARE(test_ucx_map_store_load_with_mempool)
 UCX_TEST_DECLARE(test_ucx_map_clone)
 
 
--- a/ucx/map.c	Fri Oct 05 10:25:33 2012 +0200
+++ b/ucx/map.c	Fri Oct 05 11:52:53 2012 +0200
@@ -207,7 +207,8 @@
     return 1;
 }
 
-int ucx_map_load_enc(UcxMap *map, FILE *f, copy_func decoder, void* decdata) {
+int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
+        ucx_map_coder decoder, void* decdata) {
 
     int c; int r, n;
 
@@ -268,12 +269,22 @@
         value[r] = 0;
         while (value[--r] < 33) value[r] = 0;
 
-        if (decoder == NULL) {
-            value = realloc(value, r+2);
-        } else {
-            void *decoded = decoder(value, decdata);
+        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);
@@ -283,7 +294,8 @@
     return 0;
 }
 
-int ucx_map_store_enc(UcxMap *map, FILE *f, copy_func encoder, void *encdata) {
+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;
@@ -292,10 +304,12 @@
     UCX_MAP_FOREACH(v, iter) {
         k = (char*) iter.cur->key.data;
         key = sstr(k);
-        if (encoder == NULL) {
+        if (encoder) {
+            size_t encodedSize;
+            void *encoded = encoder(v, encdata, &encodedSize);
+            value = sstrn(encoded,encodedSize - 1);
+        } else {
             value = sstr(v);
-        } else {
-            value = sstr(encoder(v, encdata));
         }
 
         written = 0;
@@ -304,7 +318,7 @@
         written += fwrite(value.ptr, 1, value.length, f);
         written += fwrite("\n", 1, 1, f);
 
-        if (encoder != NULL) {
+        if (encoder) {
             free(value.ptr);
         }
 
--- a/ucx/map.h	Fri Oct 05 10:25:33 2012 +0200
+++ b/ucx/map.h	Fri Oct 05 11:52:53 2012 +0200
@@ -7,6 +7,7 @@
 
 #include "ucx.h"
 #include "string.h"
+#include "mempool.h"
 #include <stdio.h>
 
 #ifdef	__cplusplus
@@ -21,6 +22,14 @@
 typedef struct UcxMapElement   UcxMapElement;
 typedef struct UcxMapIterator  UcxMapIterator;
 
+/*
+ * param 1: element
+ * param 2: additional data
+ * param 3: size of encoded data will be stored here
+ * returns encoded / decoded string or NULL on failure
+ */
+typedef void*(*ucx_map_coder)(void*,void*,size_t*);
+
 struct UcxMap {
     UcxMapElement **map;
     size_t        size;
@@ -67,12 +76,14 @@
 int ucx_map_iter_next(UcxMapIterator *i, void **elm);
 
 /* use macros for string maps only, values are not encoded */
-#define ucx_map_load(map, f) ucx_map_load_enc(map, f, NULL, NULL)
+#define ucx_map_load(map, f, alloc) ucx_map_load_enc(map, f, alloc, NULL, NULL)
 #define ucx_map_store(map, f) ucx_map_store_enc(map, f, NULL, NULL)
 
-int ucx_map_load_enc(UcxMap *map, FILE *f, copy_func decoder, void* decdata);
+int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
+        ucx_map_coder decoder, void* decdata);
 /* encoders shall provide null terminated strings*/
-int ucx_map_store_enc(UcxMap *map, FILE *f, copy_func encoder, void* encdata);
+int ucx_map_store_enc(UcxMap *map, FILE *f,
+        ucx_map_coder encoder, void* encdata);
 
 #ifdef	__cplusplus
 }
--- a/ucx/mempool.c	Fri Oct 05 10:25:33 2012 +0200
+++ b/ucx/mempool.c	Fri Oct 05 11:52:53 2012 +0200
@@ -24,6 +24,16 @@
     rd->destructor(rd->ptr);
 }
 
+void *ucx_default_malloc(UcxMempool *ignore, size_t n) {
+    return malloc(n);
+}
+void *ucx_default_calloc(UcxMempool *ignore, size_t n, size_t size) {
+    return calloc(n, size);
+}
+void *ucx_default_realloc(UcxMempool *ignore, void *data, size_t n) {
+    return realloc(data, n);
+}
+
 UcxMempool *ucx_mempool_new(size_t n) {
     UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool));
     if (pool == NULL) return NULL;
--- a/ucx/mempool.h	Fri Oct 05 10:25:33 2012 +0200
+++ b/ucx/mempool.h	Fri Oct 05 11:52:53 2012 +0200
@@ -19,6 +19,26 @@
     size_t size;
 } UcxMempool;
 
+typedef void*(*ucx_allocator_malloc)(UcxMempool *pool, size_t n);
+typedef void*(*ucx_allocator_calloc)(UcxMempool *pool, size_t n, size_t size);
+typedef void*(*ucx_allocator_realloc)(UcxMempool *pool, void *data, size_t n);
+
+typedef struct {
+    UcxMempool *pool;
+    ucx_allocator_malloc malloc;
+    ucx_allocator_calloc calloc;
+    ucx_allocator_realloc realloc;
+} UcxAllocator;
+
+#define UCX_ALLOCATOR_DEFAULT {NULL, \
+    ucx_default_malloc, ucx_default_calloc, ucx_default_realloc}
+#define UCX_ALLOCATOR_MEMPOOL(pool) {pool, \
+    ucx_mempool_malloc, ucx_mempool_calloc, ucx_mempool_realloc}
+
+void *ucx_default_malloc(UcxMempool *ignore, size_t n);
+void *ucx_default_calloc(UcxMempool *ignore, size_t n, size_t size);
+void *ucx_default_realloc(UcxMempool *ignore, void *data, size_t n);
+
 #define ucx_mempool_new_default() ucx_mempool_new(16)
 UcxMempool *ucx_mempool_new(size_t n);
 int ucx_mempool_chcap(UcxMempool *pool, size_t newcap);

mercurial