# HG changeset patch # User Olaf Wintermann # Date 1373814694 -7200 # Node ID 75cb6590358ba1556590515614ed5314d303da5f # Parent d2b1e67b2b48f25a8e37c3fd6ad269e515f7b27f added properties load/store functions diff -r d2b1e67b2b48 -r 75cb6590358b test/main.c --- a/test/main.c Fri Jul 12 20:50:18 2013 +0200 +++ b/test/main.c Sun Jul 14 17:11:34 2013 +0200 @@ -176,6 +176,9 @@ ucx_test_register(suite, test_ucx_prop_parse_multi); ucx_test_register(suite, test_ucx_prop_parse_part); ucx_test_register(suite, test_ucx_prop_parse_long); + ucx_test_register(suite, test_ucx_prop_parse2map); + ucx_test_register(suite, test_ucx_properties_load); + ucx_test_register(suite, test_ucx_properties_store); /* UcxBuffer Tests */ ucx_test_register(suite, test_ucx_buffer_seektell); diff -r d2b1e67b2b48 -r 75cb6590358b test/prop_tests.c --- a/test/prop_tests.c Fri Jul 12 20:50:18 2013 +0200 +++ b/test/prop_tests.c Sun Jul 14 17:11:34 2013 +0200 @@ -43,7 +43,7 @@ } UCX_TEST_IMPLEMENT(test_ucx_prop_parse) { - char *tests[] = { + const char *tests[] = { "name = value\n", "name=value\n", "n=value\n", @@ -56,7 +56,7 @@ "name = value\n\n" }; - char *names[] = { + const char *names[] = { "name", "name", "n", @@ -69,7 +69,7 @@ "name" }; - char *values[] = { + const char *values[] = { "value", "value", "value", @@ -90,13 +90,13 @@ for(int i=0;i<10;i++) { UcxPropParser *parser = ucx_prop_new(); - ucx_prop_fill(parser, tests[i], strlen(tests[i])); + ucx_prop_fill(parser, (char*)tests[i], strlen(tests[i])); UCX_TEST_ASSERT(parser->buffer == tests[i], "fill failed"); UCX_TEST_ASSERT(parser->buflen == strlen(tests[i]), "wrong buflen"); int r = ucx_prop_parse(parser, &name, &value); - sstr_t n = sstr(names[i]); - sstr_t v = sstr(values[i]); + sstr_t n = sstr((char*)names[i]); + sstr_t v = sstr((char*)values[i]); UCX_TEST_ASSERT(r == 1, "parse returned 0"); UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong property name"); UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong property value"); @@ -114,7 +114,7 @@ } UCX_TEST_IMPLEMENT(test_ucx_prop_parse_multi) { - char *names[] = { + const char *names[] = { "a", "b", "c", @@ -125,7 +125,7 @@ "key3" }; - char *values[] = { + const char *values[] = { "a value", "b value", "core", @@ -136,7 +136,7 @@ "value3" }; - char *str = "#\n" + const char *str = "#\n" "# properties\n" "# contains key/value pairs\n" "#\n" @@ -157,15 +157,16 @@ UCX_TEST_BEGIN - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); sstr_t name; sstr_t value; for(int i=0;i<8;i++) { int r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr(names[i]))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr(values[i]))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)names[i]))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)values[i]))), + "wrong value"); } int r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); @@ -177,7 +178,7 @@ UCX_TEST_IMPLEMENT(test_ucx_prop_parse_part) { UcxPropParser *parser = ucx_prop_new(); - char *str; + const char *str; int r; sstr_t name; sstr_t value; @@ -185,100 +186,100 @@ UCX_TEST_BEGIN str = ""; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = " \n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "name"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = " "; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "= "; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "value"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "\n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value"); // second round str = "#comment\n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "#comment\nname = "; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "value\na = b\n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value"); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr("b"))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"b"))), "wrong value"); str = "# comment\n#\n#\ntests = "; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "test1 "; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "test2 test3 test4\n"; - sstr_t testv = sstr("test1 test2 test3 test4"); - ucx_prop_fill(parser, str, strlen(str)); + sstr_t testv = sstr((char*)"test1 test2 test3 test4"); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("tests"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"tests"))), "wrong name"); UCX_TEST_ASSERT((!sstrcmp(value, testv)), "wrong value"); // test if parse finds a name/value after a tmp comment str = "# just a comment"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = " in 3"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = " parts\na = 1\n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr("1"))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"1"))), "wrong value"); UCX_TEST_END @@ -320,8 +321,8 @@ r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); - char *str = " = "; - ucx_prop_fill(parser, str, strlen(str)); + const char *str = " = "; + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); @@ -338,7 +339,7 @@ UCX_TEST_ASSERT(r == 0, "parse returned 1"); str = "\n#comment\nkey = value\n"; - ucx_prop_fill(parser, str, strlen(str)); + ucx_prop_fill(parser, (char*)str, strlen(str)); r = ucx_prop_parse(parser, &name, &value); sstr_t n = sstrn(long_name, name_len); sstr_t v = sstrn(long_value, value_len); @@ -348,8 +349,8 @@ r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 1, "parse returned 0"); - UCX_TEST_ASSERT((!sstrcmp(name, sstr("key"))), "wrong name"); - UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); + UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"key"))), "wrong name"); + UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value"); r = ucx_prop_parse(parser, &name, &value); UCX_TEST_ASSERT(r == 0, "parse returned 1"); @@ -360,3 +361,182 @@ free(long_value); ucx_prop_free(parser); } + +UCX_TEST_IMPLEMENT(test_ucx_prop_parse2map) { + UcxMap *map = ucx_map_new(16); + UcxPropParser *parser = ucx_prop_new(); + + UCX_TEST_BEGIN + + const char *str = "key1 = value1\nkey2 = value2\n\n#comment\n\nkey3 = value3\n"; + ucx_prop_fill(parser, (char*)str, strlen(str)); + + int r = ucx_prop_parse2map(parser, map); + + UCX_TEST_ASSERT(r == 0, "parse2map failed"); + UCX_TEST_ASSERT(map->count == 3, "wrong number of properties"); + + char *v1 = (char*)ucx_map_cstr_get(map, "key1"); + char *v2 = (char*)ucx_map_cstr_get(map, "key2"); + char *v3 = (char*)ucx_map_cstr_get(map, "key3"); + + UCX_TEST_ASSERT(v1, "value for key1 not found"); + UCX_TEST_ASSERT(v2, "value for key2 not found"); + UCX_TEST_ASSERT(v3, "value for key3 not found"); + + UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1"); + UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2"); + UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3"); + + // second test + ucx_map_free(map); + free(v1); + free(v2); + free(v3); + map = ucx_map_new(16); + + str = "\n#comment\n"; + ucx_prop_fill(parser, (char*)str, strlen(str)); + + r = ucx_prop_parse2map(parser, map); + UCX_TEST_ASSERT(r == 0, "parse2map failed"); + UCX_TEST_ASSERT(map->count == 0, "wrong number of properties"); + + str = "key1 = value1\nsyntax error line\n"; + ucx_prop_fill(parser, (char*)str, strlen(str)); + + r = ucx_prop_parse2map(parser, map); + UCX_TEST_ASSERT(r == 1, "parse2map should return 1"); + UCX_TEST_ASSERT(map->count == 1, "wrong number of properties"); + + char *v = (char*)ucx_map_cstr_get(map, "key1"); + UCX_TEST_ASSERT((!strcmp(v, "value1")), "wrong value"); + + UCX_TEST_END + + ucx_prop_free(parser); +} + +UCX_TEST_IMPLEMENT(test_ucx_properties_load) { + UCX_TEST_BEGIN + FILE *f = tmpfile(); + UCX_TEST_ASSERT(f, "test file cannot be opened, test aborted"); + + fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n"); + fprintf(f, "\n\nkey3 = value3\n\n"); + + size_t name_len = 512; + char *long_name = (char*)malloc(name_len); + memset(long_name, 'k', 512); + + size_t value_len = 2048; + char *long_value = (char*)malloc(value_len); + memset(long_value, 'v', 2048); + + fwrite(long_name, 1, name_len, f); + fprintf(f, " = "); + fwrite(long_value, 1, value_len, f); + fprintf(f, " \n"); + + fprintf(f, "\n\n\n\nlast_key = property value\n"); + + fflush(f); + fseek(f, 0, SEEK_SET); + + UcxMap *map = ucx_map_new(8); + int r = ucx_properties_load(map, f); + + UCX_TEST_ASSERT(r == 0, "ucx_properties_load failed"); + UCX_TEST_ASSERT(map->count == 5, "wrong number of properties"); + + char *v1 = (char*)ucx_map_cstr_get(map, "key1"); + char *v2 = (char*)ucx_map_cstr_get(map, "key2"); + char *v3 = (char*)ucx_map_cstr_get(map, "key3"); + char *lv = (char*)ucx_map_sstr_get(map, sstrn(long_name, name_len)); + char *lk = (char*)ucx_map_cstr_get(map, "last_key"); + + UCX_TEST_ASSERT(v1, "value for key1 not found"); + UCX_TEST_ASSERT(v2, "value for key2 not found"); + UCX_TEST_ASSERT(v3, "value for key3 not found"); + UCX_TEST_ASSERT(lv, "value for long key not found"); + UCX_TEST_ASSERT(lk, "value for last_key not found"); + + UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1"); + UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2"); + UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3"); + sstr_t long1 = sstrn(long_value, value_len); + sstr_t long2 = sstr(lv); + UCX_TEST_ASSERT((!sstrcmp(long1, long2)), "wrong value for long key"); + UCX_TEST_ASSERT(!strcmp(lk, "property value"), "wrong value for last_key"); + + free(v1); + free(v2); + free(v3); + free(lv); + free(lk); + ucx_map_free(map); + fclose(f); + + UCX_TEST_END +} + +UCX_TEST_IMPLEMENT(test_ucx_properties_store) { + UcxMap *map1 = ucx_map_new(16); + ucx_map_cstr_put(map1, "key1", "value1"); + ucx_map_cstr_put(map1, "key2", "value2"); + ucx_map_cstr_put(map1, "key3", "value3"); + ucx_map_cstr_put(map1, "key4", "value4"); + ucx_map_cstr_put(map1, "property.key1", "some value 1"); + ucx_map_cstr_put(map1, "property.key2", "some value 2"); + ucx_map_cstr_put(map1, "property.key3", "some value 3"); + ucx_map_cstr_put(map1, "property.key4", "some value 4"); + + UCX_TEST_BEGIN + + FILE *f = tmpfile(); + fprintf(f, "#\n# test property file\n#\n#\n"); + ucx_properties_store(map1, f); + + fflush(f); + fseek(f, 0, SEEK_SET); + UcxMap *map2 = ucx_map_new(16); + ucx_properties_load(map2, f); + + UCX_TEST_ASSERT(map2->count == 8, "wrong number of properties in map2"); + + char *v1 = (char*)ucx_map_cstr_get(map2, "key1"); + char *v2 = (char*)ucx_map_cstr_get(map2, "key2"); + char *v3 = (char*)ucx_map_cstr_get(map2, "key3"); + char *v4 = (char*)ucx_map_cstr_get(map2, "key4"); + char *v5 = (char*)ucx_map_cstr_get(map2, "property.key1"); + char *v6 = (char*)ucx_map_cstr_get(map2, "property.key2"); + char *v7 = (char*)ucx_map_cstr_get(map2, "property.key3"); + char *v8 = (char*)ucx_map_cstr_get(map2, "property.key4"); + + UCX_TEST_ASSERT(v1 && v2 && v3 && v4 && v5 && v6 && v7 && v8, + "missing values"); + + UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value 1"); + UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value 2"); + UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value 3"); + UCX_TEST_ASSERT((!strcmp(v4, "value4")), "wrong value 4"); + UCX_TEST_ASSERT((!strcmp(v5, "some value 1")), "wrong value 5"); + UCX_TEST_ASSERT((!strcmp(v6, "some value 2")), "wrong value 6"); + UCX_TEST_ASSERT((!strcmp(v7, "some value 3")), "wrong value 7"); + UCX_TEST_ASSERT((!strcmp(v8, "some value 4")), "wrong value 8"); + + free(v1); + free(v2); + free(v3); + free(v4); + free(v5); + free(v6); + free(v7); + free(v8); + ucx_map_free(map2); + fclose(f); + + UCX_TEST_END + + ucx_map_free(map1); +} diff -r d2b1e67b2b48 -r 75cb6590358b test/prop_tests.h --- a/test/prop_tests.h Fri Jul 12 20:50:18 2013 +0200 +++ b/test/prop_tests.h Sun Jul 14 17:11:34 2013 +0200 @@ -41,6 +41,9 @@ UCX_TEST_DECLARE(test_ucx_prop_parse_multi); UCX_TEST_DECLARE(test_ucx_prop_parse_part); UCX_TEST_DECLARE(test_ucx_prop_parse_long); +UCX_TEST_DECLARE(test_ucx_prop_parse2map); +UCX_TEST_DECLARE(test_ucx_properties_load); +UCX_TEST_DECLARE(test_ucx_properties_store); #ifdef __cplusplus } diff -r d2b1e67b2b48 -r 75cb6590358b ucx/map.h --- a/ucx/map.h Fri Jul 12 20:50:18 2013 +0200 +++ b/ucx/map.h Sun Jul 14 17:11:34 2013 +0200 @@ -94,11 +94,11 @@ void* ucx_map_remove(UcxMap *map, UcxKey key); #define ucx_map_sstr_put(m, s, d) \ - ucx_map_put(m, ucx_key(s.ptr, s.length), d) + ucx_map_put(m, ucx_key(s.ptr, s.length), (void*)d) #define ucx_map_cstr_put(m, s, d) \ - ucx_map_put(m, ucx_key((void*)s, strlen(s)), d) + ucx_map_put(m, ucx_key((void*)s, strlen(s)), (void*)d) #define ucx_map_int_put(m, i, d) \ - ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), d) + ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), (void*)d) #define ucx_map_sstr_get(m, s) \ ucx_map_get(m, ucx_key(s.ptr, s.length)) diff -r d2b1e67b2b48 -r 75cb6590358b ucx/properties.c --- a/ucx/properties.c Fri Jul 12 20:50:18 2013 +0200 +++ b/ucx/properties.c Sun Jul 14 17:11:34 2013 +0200 @@ -45,6 +45,7 @@ parser->tmp = NULL; parser->tmplen = 0; parser->tmpcap = 0; + parser->error = 0; parser->delimiter = '='; parser->comment1 = '#'; parser->comment2 = 0; @@ -106,7 +107,7 @@ parser->pos = newlen; /* - * if ret == 0 the tmp buffer contained just space or comment + * if ret == 0 the tmp buffer contained just space or a comment * we parse again with the original buffer to get a name/value * or a new tmp buffer */ @@ -126,10 +127,7 @@ char delimiter = parser->delimiter; // get one line and parse it - while(1) { - if(parser->pos >= parser->buflen) { - return 0; - } + while(parser->pos < parser->buflen) { char *buf = parser->buffer + parser->pos; size_t len = parser->buflen - parser->pos; @@ -160,7 +158,7 @@ } if(c != '\n') { - // we have not enough data for a line + // we don't have enough data for a line // store remaining bytes in temporary buffer for next round parser->tmpcap = len + 128; parser->tmp = (char*)malloc(parser->tmpcap); @@ -174,31 +172,96 @@ if(delimiter_index == 0) { line = sstrtrim(line); if(line.length != 0) { - // syntax error - // TODO + parser->error = 1; } - parser->pos += i + 1; - continue; + } else { + sstr_t n = sstrn(buf, delimiter_index); + sstr_t v = sstrn(buf+delimiter_index+1, i-delimiter_index-1); + n = sstrtrim(n); + v = sstrtrim(v); + if(n.length != 0 || v.length != 0) { + *name = n; + *value = v; + parser->pos += i + 1; + return 1; + } else { + parser->error = 1; + } } - sstr_t n = sstrn(buf, delimiter_index); - sstr_t v = sstrn(buf + delimiter_index + 1, i - delimiter_index - 1); - n = sstrtrim(n); - v = sstrtrim(v); - if(n.length == 0 || v.length == 0) { - // syntax error - // TODO - parser->pos += i + 1; - continue; - } - - *name = n; - *value = v; - parser->pos += i + 1; - break; } - return 1; + return 0; } +int ucx_prop_parse2map(UcxPropParser *parser, UcxMap *map) { + sstr_t name; + sstr_t value; + while(ucx_prop_parse(parser, &name, &value)) { + name = sstrdup_alloc(map->allocator, name); + if(!name.ptr) { + return 1; + } + value = sstrdup_alloc(map->allocator, value); + if(!value.ptr) { + map->allocator->free(map->allocator->pool, value.ptr); + return 1; + } + if(ucx_map_sstr_put(map, name, value.ptr)) { + map->allocator->free(map->allocator->pool, name.ptr); + map->allocator->free(map->allocator->pool, value.ptr); + return 1; + } + } + if(parser->error) { + return 1; + } else { + return 0; + } +} + +int ucx_properties_load(UcxMap *map, FILE *file) { + UcxPropParser *parser = ucx_prop_new(); + if(!parser || !map || !file) { + return 1; + } + + int error = 0; + size_t r; + char buf[1024]; + while((r = fread(buf, 1, 1024, file)) != 0) { + ucx_prop_fill(parser, buf, r); + if(ucx_prop_parse2map(parser, map)) { + error = 1; + break; + } + } + + ucx_prop_free(parser); + return error; +} + +int ucx_properties_store(UcxMap *map, FILE *file) { + UcxMapIterator iter = ucx_map_iterator(map); + char *k, *v; + sstr_t key, value; + size_t written; + + UCX_MAP_FOREACH(v, iter) { + k = (char*) iter.cur->key.data; + key = sstrn(k, iter.cur->key.len); + value = sstr(v); + + written = 0; + written += fwrite(key.ptr, 1, key.length, file); + written += fwrite(" = ", 1, 3, file); + written += fwrite(value.ptr, 1, value.length, file); + written += fwrite("\n", 1, 1, file); + + if (written != key.length + value.length + 4) return 1; + } + + return 0; +} + diff -r d2b1e67b2b48 -r 75cb6590358b ucx/properties.h --- a/ucx/properties.h Fri Jul 12 20:50:18 2013 +0200 +++ b/ucx/properties.h Sun Jul 14 17:11:34 2013 +0200 @@ -43,6 +43,7 @@ char *tmp; size_t tmplen; size_t tmpcap; + int error; char delimiter; char comment1; char comment2; @@ -54,6 +55,10 @@ void ucx_prop_free(UcxPropParser *parser); void ucx_prop_fill(UcxPropParser *parser, char *buf, size_t len); int ucx_prop_parse(UcxPropParser *parser, sstr_t *name, sstr_t *value); +int ucx_prop_parse2map(UcxPropParser *parser, UcxMap *map); + +int ucx_properties_load(UcxMap *map, FILE *file); +int ucx_properties_store(UcxMap *map, FILE *file); #ifdef __cplusplus } diff -r d2b1e67b2b48 -r 75cb6590358b ucx/string.c --- a/ucx/string.c Fri Jul 12 20:50:18 2013 +0200 +++ b/ucx/string.c Sun Jul 14 17:11:34 2013 +0200 @@ -31,6 +31,7 @@ #include #include "string.h" +#include "allocator.h" sstr_t sstr(char *s) { sstr_t string; @@ -180,16 +181,30 @@ sstr_t sstrdup(sstr_t s) { sstr_t newstring; newstring.ptr = (char*) malloc(s.length + 1); - newstring.length = 0; if (newstring.ptr) { newstring.length = s.length; newstring.ptr[newstring.length] = 0; - + memcpy(newstring.ptr, s.ptr, s.length); } else { newstring.length = 0; } + + return newstring; +} +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s) { + sstr_t newstring; + newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1); + if (newstring.ptr) { + newstring.length = s.length; + newstring.ptr[newstring.length] = 0; + + memcpy(newstring.ptr, s.ptr, s.length); + } else { + newstring.length = 0; + } + return newstring; } diff -r d2b1e67b2b48 -r 75cb6590358b ucx/string.h --- a/ucx/string.h Fri Jul 12 20:50:18 2013 +0200 +++ b/ucx/string.h Sun Jul 14 17:11:34 2013 +0200 @@ -30,6 +30,7 @@ #define _SSTRING_H #include "ucx.h" +#include "allocator.h" #include /* use macros for literals only */ @@ -117,6 +118,7 @@ int sstrcmp(sstr_t s1, sstr_t s2); sstr_t sstrdup(sstr_t s); +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s); sstr_t sstrtrim(sstr_t string);