Thu, 04 Oct 2012 16:03:18 +0200
(broken-commit) - added load and store functions, tests failing
some evil crash happens when executing the test - remove the strcmp calls in the test case for the store and load function and everything "works"
the error must be somewhere else - maybe something that should not be freed is freed during the test
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/string.h | file | annotate | diff | comparison | revisions | |
ucx/ucx.h | file | annotate | diff | comparison | revisions |
--- a/test/main.c Thu Oct 04 14:08:31 2012 +0200 +++ b/test/main.c Thu Oct 04 16:03:18 2012 +0200 @@ -147,6 +147,7 @@ ucx_test_register(suite, test_ucx_map_get); 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); /* sstring Tests */ ucx_test_register(suite, test_sstrsplit);
--- a/test/map_tests.c Thu Oct 04 14:08:31 2012 +0200 +++ b/test/map_tests.c Thu Oct 04 16:03:18 2012 +0200 @@ -136,3 +136,55 @@ UCX_TEST_END ucx_map_free(map); } + +UCX_TEST_IMPLEMENT(test_ucx_map_store_load) { + 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, "other.very.long.key", "value"); + ucx_map_cstr_put(map, "testkey", "testvalue"); + ucx_map_cstr_put(map, "simple", "not a key but an extremely long value " + "to test if the buffer extension works as designed"); + + FILE *f = fopen("test_ucx_map_store", "w"); + int r; + + fwrite(" # comment test", 1, 15, f); + r = ucx_map_store(map, f); + fwrite("#discard this", 1, 13, f); + + fclose(f); + ucx_map_free(map); + map = ucx_map_new(1); + f = fopen("test_ucx_map_store", "r"); + r += ucx_map_load(map, f); + + UCX_TEST_BEGIN + char *value; + UCX_TEST_ASSERT(r == 0, "IO errors, test cannot be performed"); + + value = ucx_map_cstr_get(map, "test"); + UCX_TEST_ASSERT(strcmp(value, "test") == 0, "value error for key: test"); + + value = ucx_map_cstr_get(map, "key"); + UCX_TEST_ASSERT(strcmp(value, "value") == 0, "value error for key: key"); + + value = ucx_map_cstr_get(map, "other.very.long.key"); + UCX_TEST_ASSERT(strcmp(value, "value") == 0, + "value error for key: other.very.long.key"); + + value = ucx_map_cstr_get(map, "testkey"); + UCX_TEST_ASSERT(strcmp(value, "testvalue") == 0, + "value error for key: testkey"); + + value = ucx_map_cstr_get(map, "simple"); + UCX_TEST_ASSERT(strcmp(value, "not a key but an extremely long value " + "to test if the buffer extension works as designed") == 0, + "value error for key: simple"); + + UCX_TEST_END + fclose(f); + + unlink("test_ucx_map_store"); +}
--- a/test/map_tests.h Thu Oct 04 14:08:31 2012 +0200 +++ b/test/map_tests.h Thu Oct 04 16:03:18 2012 +0200 @@ -18,6 +18,7 @@ UCX_TEST_DECLARE(test_ucx_map_get) UCX_TEST_DECLARE(test_ucx_map_iterator) UCX_TEST_DECLARE(test_ucx_map_iterator_chain) +UCX_TEST_DECLARE(test_ucx_map_store_load) #ifdef __cplusplus
--- a/ucx/map.c Thu Oct 04 14:08:31 2012 +0200 +++ b/ucx/map.c Thu Oct 04 16:03:18 2012 +0200 @@ -189,3 +189,83 @@ return 1; } + +int ucx_map_load(UcxMap *map, FILE *f) { + + char c; int r, n; + + char *key, *value; + + while ((c = (char) fgetc(f)) > 0) { + /* Discard leading spaces and comments */ + if (c == ' ') 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 = (char) fgetc(f)) > 0); + if (c == 0) { + free(key); + return 1; + } + key[r] = 0; + + /* read into value buffer */ + n = 64; + value = malloc(n); + r = 0; + while ((c = (char) fgetc(f)) > 0) { + if (c == '\n') break; + if (r > n - 1) { + n *= 2; + value = realloc(value, n); + } + value[r] = c; + r++; + } + value = realloc(value, r+1); + value[r] = 0; + + ucx_map_cstr_put(map, key, value); + free(key); + } + + return 0; +} + +int ucx_map_store(UcxMap *map, FILE *f) { + 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); 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 (written != key.length + value.length + 4) return 1; + } + + return 0; +}
--- a/ucx/map.h Thu Oct 04 14:08:31 2012 +0200 +++ b/ucx/map.h Thu Oct 04 16:03:18 2012 +0200 @@ -14,7 +14,7 @@ #endif #define UCX_MAP_FOREACH(elm,iter) \ - for(elm;ucx_map_iter_next(&iter,(void*)&elm)==0;) + for(;ucx_map_iter_next(&iter,(void*)&elm)==0;) typedef struct UcxMap UcxMap; typedef struct UcxKey UcxKey; @@ -64,6 +64,15 @@ int ucx_map_iter_next(UcxMapIterator *i, void **elm); +/* use for string maps only, values are not encoded */ +int ucx_map_load(UcxMap *map, FILE *f); +int ucx_map_store(UcxMap *map, FILE *f); + +/* TODO: +int ucx_map_load_enc(UcxMap *map, FILE *f, copy_func decoder, void* decdata); +int ucx_map_store_enc(UcxMap *map, FILE *f, copy_func encoder, void* encdata); + */ + #ifdef __cplusplus } #endif
--- a/ucx/string.h Thu Oct 04 14:08:31 2012 +0200 +++ b/ucx/string.h Thu Oct 04 16:03:18 2012 +0200 @@ -10,6 +10,7 @@ #include <stddef.h> +/* use macros for literals only */ #define S(s) { s, sizeof(s)-1 } #define ST(s) sstrn(s, sizeof(s)-1)
--- a/ucx/ucx.h Thu Oct 04 14:08:31 2012 +0200 +++ b/ucx/ucx.h Thu Oct 04 16:03:18 2012 +0200 @@ -17,9 +17,6 @@ #define UCX_FOREACH(type,list,elem) \ for (type elem = list ; elem != NULL ; elem = elem->next) -/* source,data -> errno */ -typedef int(*ucx_callback)(void*,void*); - /* element1,element2,custom data -> {-1,0,1} */ typedef int(*cmp_func)(void*,void*,void*);