Fri, 05 Oct 2012 11:52:53 +0200
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);