# HG changeset patch # User Mike Becker # Date 1349430773 -7200 # Node ID 621a4430c404813e2b3cf62c23ebb96a5e0fc32a # Parent 48ca036d7d9caca1e6a1b22cb612a0ae870ac550 map can now load values from file into pooled memory use with care when using a decoder that also allocates memory diff -r 48ca036d7d9c -r 621a4430c404 test/main.c --- 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 */ diff -r 48ca036d7d9c -r 621a4430c404 test/map_tests.c --- 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) { diff -r 48ca036d7d9c -r 621a4430c404 test/map_tests.h --- 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) diff -r 48ca036d7d9c -r 621a4430c404 ucx/map.c --- 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); } diff -r 48ca036d7d9c -r 621a4430c404 ucx/map.h --- 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 #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 } diff -r 48ca036d7d9c -r 621a4430c404 ucx/mempool.c --- 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; diff -r 48ca036d7d9c -r 621a4430c404 ucx/mempool.h --- 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);