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
     1.1 --- a/test/main.c	Fri Oct 05 10:25:33 2012 +0200
     1.2 +++ b/test/main.c	Fri Oct 05 11:52:53 2012 +0200
     1.3 @@ -148,6 +148,7 @@
     1.4          ucx_test_register(suite, test_ucx_map_iterator);
     1.5          ucx_test_register(suite, test_ucx_map_iterator_chain);
     1.6          ucx_test_register(suite, test_ucx_map_store_load);
     1.7 +        ucx_test_register(suite, test_ucx_map_store_load_with_mempool);
     1.8          ucx_test_register(suite, test_ucx_map_clone);
     1.9          
    1.10          /* sstring Tests */
     2.1 --- a/test/map_tests.c	Fri Oct 05 10:25:33 2012 +0200
     2.2 +++ b/test/map_tests.c	Fri Oct 05 11:52:53 2012 +0200
     2.3 @@ -141,7 +141,7 @@
     2.4      ucx_map_free(map);
     2.5  }
     2.6  
     2.7 -void* test_ucx_map_store_load_encdec(void *value, void *data) {
     2.8 +void* test_ucx_map_store_load_encdec(void *value, void *data, size_t *size) {
     2.9      char *string = (char*) value;
    2.10      size_t n = strlen(string);
    2.11      char *encoded = malloc(n+1);
    2.12 @@ -149,6 +149,7 @@
    2.13          encoded[i] = string[n-1-i];
    2.14      }
    2.15      encoded[n] = 0;
    2.16 +    *size = n+1;
    2.17      return encoded;
    2.18  }
    2.19  
    2.20 @@ -173,7 +174,11 @@
    2.21      ucx_map_free(map);
    2.22      map = ucx_map_new(1);
    2.23      f = fopen("test_ucx_map_store", "r");
    2.24 -    r += ucx_map_load_enc(map, f, test_ucx_map_store_load_encdec, NULL);
    2.25 +    UcxAllocator allocator = UCX_ALLOCATOR_DEFAULT;
    2.26 +    r += ucx_map_load_enc(map, f, allocator,
    2.27 +            test_ucx_map_store_load_encdec, NULL);
    2.28 +    fclose(f);
    2.29 +    unlink("test_ucx_map_store");
    2.30  
    2.31      UCX_TEST_BEGIN
    2.32      char *value;
    2.33 @@ -205,9 +210,43 @@
    2.34              "value error for key: simple");
    2.35  
    2.36      UCX_TEST_END
    2.37 +}
    2.38 +
    2.39 +UCX_TEST_IMPLEMENT(test_ucx_map_store_load_with_mempool) {
    2.40 +    UcxMap *map = ucx_map_new(4);
    2.41 +
    2.42 +    ucx_map_cstr_put(map, "test", "test");
    2.43 +    ucx_map_cstr_put(map, "key", "value");
    2.44 +    ucx_map_cstr_put(map, "testkey", "testvalue");
    2.45 +    ucx_map_cstr_put(map, "simple", "a simple value");
    2.46 +
    2.47 +    FILE *f = fopen("test_ucx_map_store", "w");
    2.48 +    int r;
    2.49 +    r = ucx_map_store_enc(map, f, NULL, NULL);
    2.50      fclose(f);
    2.51 +    ucx_map_free(map);
    2.52  
    2.53 +    UcxMempool *pool = ucx_mempool_new(4);
    2.54 +    map = ucx_map_new(4);
    2.55 +    f = fopen("test_ucx_map_store", "r");
    2.56 +    UcxAllocator allocator = UCX_ALLOCATOR_MEMPOOL(pool);
    2.57 +    r += ucx_map_load_enc(map, f, allocator,
    2.58 +            test_ucx_map_store_load_encdec, NULL);
    2.59 +    fclose(f);
    2.60      unlink("test_ucx_map_store");
    2.61 +
    2.62 +    UCX_TEST_BEGIN
    2.63 +    UCX_TEST_ASSERT(r == 0, "IO errors, test cannot be performed");
    2.64 +    UcxMapIterator iter = ucx_map_iterator(map);
    2.65 +    char *value; size_t n;
    2.66 +    UCX_MAP_FOREACH(value, iter) {
    2.67 +        n = strlen(value);
    2.68 +        UCX_TEST_ASSERT(strncmp(pool->data[iter.index], value, n),
    2.69 +                "values of map does not match pooled values");
    2.70 +    }
    2.71 +    UCX_TEST_END
    2.72 +
    2.73 +    ucx_mempool_free(pool);
    2.74  }
    2.75  
    2.76  UCX_TEST_IMPLEMENT(test_ucx_map_clone) {
     3.1 --- a/test/map_tests.h	Fri Oct 05 10:25:33 2012 +0200
     3.2 +++ b/test/map_tests.h	Fri Oct 05 11:52:53 2012 +0200
     3.3 @@ -19,6 +19,7 @@
     3.4  UCX_TEST_DECLARE(test_ucx_map_iterator)
     3.5  UCX_TEST_DECLARE(test_ucx_map_iterator_chain)
     3.6  UCX_TEST_DECLARE(test_ucx_map_store_load)
     3.7 +UCX_TEST_DECLARE(test_ucx_map_store_load_with_mempool)
     3.8  UCX_TEST_DECLARE(test_ucx_map_clone)
     3.9  
    3.10  
     4.1 --- a/ucx/map.c	Fri Oct 05 10:25:33 2012 +0200
     4.2 +++ b/ucx/map.c	Fri Oct 05 11:52:53 2012 +0200
     4.3 @@ -207,7 +207,8 @@
     4.4      return 1;
     4.5  }
     4.6  
     4.7 -int ucx_map_load_enc(UcxMap *map, FILE *f, copy_func decoder, void* decdata) {
     4.8 +int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
     4.9 +        ucx_map_coder decoder, void* decdata) {
    4.10  
    4.11      int c; int r, n;
    4.12  
    4.13 @@ -268,12 +269,22 @@
    4.14          value[r] = 0;
    4.15          while (value[--r] < 33) value[r] = 0;
    4.16  
    4.17 -        if (decoder == NULL) {
    4.18 -            value = realloc(value, r+2);
    4.19 -        } else {
    4.20 -            void *decoded = decoder(value, decdata);
    4.21 +        if (decoder) {
    4.22 +            size_t decodedSize;
    4.23 +            void *decoded = decoder(value, decdata, &decodedSize);
    4.24              free(value);
    4.25              value = decoded;
    4.26 +            r = decodedSize;
    4.27 +        } else {
    4.28 +            r += 2;
    4.29 +            value = realloc(value, r);
    4.30 +        }
    4.31 +
    4.32 +        if (allocator.pool) {
    4.33 +            void *pooledValue = allocator.malloc(allocator.pool, r);
    4.34 +            memcpy(pooledValue, value, r);
    4.35 +            free(value);
    4.36 +            value = pooledValue;
    4.37          }
    4.38  
    4.39          ucx_map_cstr_put(map, key, value);
    4.40 @@ -283,7 +294,8 @@
    4.41      return 0;
    4.42  }
    4.43  
    4.44 -int ucx_map_store_enc(UcxMap *map, FILE *f, copy_func encoder, void *encdata) {
    4.45 +int ucx_map_store_enc(UcxMap *map, FILE *f,
    4.46 +        ucx_map_coder encoder, void *encdata) {
    4.47      UcxMapIterator iter = ucx_map_iterator(map);
    4.48      char *k, *v;
    4.49      sstr_t key, value;
    4.50 @@ -292,10 +304,12 @@
    4.51      UCX_MAP_FOREACH(v, iter) {
    4.52          k = (char*) iter.cur->key.data;
    4.53          key = sstr(k);
    4.54 -        if (encoder == NULL) {
    4.55 +        if (encoder) {
    4.56 +            size_t encodedSize;
    4.57 +            void *encoded = encoder(v, encdata, &encodedSize);
    4.58 +            value = sstrn(encoded,encodedSize - 1);
    4.59 +        } else {
    4.60              value = sstr(v);
    4.61 -        } else {
    4.62 -            value = sstr(encoder(v, encdata));
    4.63          }
    4.64  
    4.65          written = 0;
    4.66 @@ -304,7 +318,7 @@
    4.67          written += fwrite(value.ptr, 1, value.length, f);
    4.68          written += fwrite("\n", 1, 1, f);
    4.69  
    4.70 -        if (encoder != NULL) {
    4.71 +        if (encoder) {
    4.72              free(value.ptr);
    4.73          }
    4.74  
     5.1 --- a/ucx/map.h	Fri Oct 05 10:25:33 2012 +0200
     5.2 +++ b/ucx/map.h	Fri Oct 05 11:52:53 2012 +0200
     5.3 @@ -7,6 +7,7 @@
     5.4  
     5.5  #include "ucx.h"
     5.6  #include "string.h"
     5.7 +#include "mempool.h"
     5.8  #include <stdio.h>
     5.9  
    5.10  #ifdef	__cplusplus
    5.11 @@ -21,6 +22,14 @@
    5.12  typedef struct UcxMapElement   UcxMapElement;
    5.13  typedef struct UcxMapIterator  UcxMapIterator;
    5.14  
    5.15 +/*
    5.16 + * param 1: element
    5.17 + * param 2: additional data
    5.18 + * param 3: size of encoded data will be stored here
    5.19 + * returns encoded / decoded string or NULL on failure
    5.20 + */
    5.21 +typedef void*(*ucx_map_coder)(void*,void*,size_t*);
    5.22 +
    5.23  struct UcxMap {
    5.24      UcxMapElement **map;
    5.25      size_t        size;
    5.26 @@ -67,12 +76,14 @@
    5.27  int ucx_map_iter_next(UcxMapIterator *i, void **elm);
    5.28  
    5.29  /* use macros for string maps only, values are not encoded */
    5.30 -#define ucx_map_load(map, f) ucx_map_load_enc(map, f, NULL, NULL)
    5.31 +#define ucx_map_load(map, f, alloc) ucx_map_load_enc(map, f, alloc, NULL, NULL)
    5.32  #define ucx_map_store(map, f) ucx_map_store_enc(map, f, NULL, NULL)
    5.33  
    5.34 -int ucx_map_load_enc(UcxMap *map, FILE *f, copy_func decoder, void* decdata);
    5.35 +int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
    5.36 +        ucx_map_coder decoder, void* decdata);
    5.37  /* encoders shall provide null terminated strings*/
    5.38 -int ucx_map_store_enc(UcxMap *map, FILE *f, copy_func encoder, void* encdata);
    5.39 +int ucx_map_store_enc(UcxMap *map, FILE *f,
    5.40 +        ucx_map_coder encoder, void* encdata);
    5.41  
    5.42  #ifdef	__cplusplus
    5.43  }
     6.1 --- a/ucx/mempool.c	Fri Oct 05 10:25:33 2012 +0200
     6.2 +++ b/ucx/mempool.c	Fri Oct 05 11:52:53 2012 +0200
     6.3 @@ -24,6 +24,16 @@
     6.4      rd->destructor(rd->ptr);
     6.5  }
     6.6  
     6.7 +void *ucx_default_malloc(UcxMempool *ignore, size_t n) {
     6.8 +    return malloc(n);
     6.9 +}
    6.10 +void *ucx_default_calloc(UcxMempool *ignore, size_t n, size_t size) {
    6.11 +    return calloc(n, size);
    6.12 +}
    6.13 +void *ucx_default_realloc(UcxMempool *ignore, void *data, size_t n) {
    6.14 +    return realloc(data, n);
    6.15 +}
    6.16 +
    6.17  UcxMempool *ucx_mempool_new(size_t n) {
    6.18      UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool));
    6.19      if (pool == NULL) return NULL;
     7.1 --- a/ucx/mempool.h	Fri Oct 05 10:25:33 2012 +0200
     7.2 +++ b/ucx/mempool.h	Fri Oct 05 11:52:53 2012 +0200
     7.3 @@ -19,6 +19,26 @@
     7.4      size_t size;
     7.5  } UcxMempool;
     7.6  
     7.7 +typedef void*(*ucx_allocator_malloc)(UcxMempool *pool, size_t n);
     7.8 +typedef void*(*ucx_allocator_calloc)(UcxMempool *pool, size_t n, size_t size);
     7.9 +typedef void*(*ucx_allocator_realloc)(UcxMempool *pool, void *data, size_t n);
    7.10 +
    7.11 +typedef struct {
    7.12 +    UcxMempool *pool;
    7.13 +    ucx_allocator_malloc malloc;
    7.14 +    ucx_allocator_calloc calloc;
    7.15 +    ucx_allocator_realloc realloc;
    7.16 +} UcxAllocator;
    7.17 +
    7.18 +#define UCX_ALLOCATOR_DEFAULT {NULL, \
    7.19 +    ucx_default_malloc, ucx_default_calloc, ucx_default_realloc}
    7.20 +#define UCX_ALLOCATOR_MEMPOOL(pool) {pool, \
    7.21 +    ucx_mempool_malloc, ucx_mempool_calloc, ucx_mempool_realloc}
    7.22 +
    7.23 +void *ucx_default_malloc(UcxMempool *ignore, size_t n);
    7.24 +void *ucx_default_calloc(UcxMempool *ignore, size_t n, size_t size);
    7.25 +void *ucx_default_realloc(UcxMempool *ignore, void *data, size_t n);
    7.26 +
    7.27  #define ucx_mempool_new_default() ucx_mempool_new(16)
    7.28  UcxMempool *ucx_mempool_new(size_t n);
    7.29  int ucx_mempool_chcap(UcxMempool *pool, size_t newcap);

mercurial