added properties load/store functions

Sun, 14 Jul 2013 17:11:34 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 14 Jul 2013 17:11:34 +0200
changeset 109
75cb6590358b
parent 108
d2b1e67b2b48
child 110
1cf71e56f01e

added properties load/store functions

test/main.c file | annotate | diff | comparison | revisions
test/prop_tests.c file | annotate | diff | comparison | revisions
test/prop_tests.h file | annotate | diff | comparison | revisions
ucx/map.h file | annotate | diff | comparison | revisions
ucx/properties.c file | annotate | diff | comparison | revisions
ucx/properties.h file | annotate | diff | comparison | revisions
ucx/string.c file | annotate | diff | comparison | revisions
ucx/string.h file | annotate | diff | comparison | revisions
     1.1 --- a/test/main.c	Fri Jul 12 20:50:18 2013 +0200
     1.2 +++ b/test/main.c	Sun Jul 14 17:11:34 2013 +0200
     1.3 @@ -176,6 +176,9 @@
     1.4          ucx_test_register(suite, test_ucx_prop_parse_multi);
     1.5          ucx_test_register(suite, test_ucx_prop_parse_part);
     1.6          ucx_test_register(suite, test_ucx_prop_parse_long);
     1.7 +        ucx_test_register(suite, test_ucx_prop_parse2map);
     1.8 +        ucx_test_register(suite, test_ucx_properties_load);
     1.9 +        ucx_test_register(suite, test_ucx_properties_store);
    1.10          
    1.11          /* UcxBuffer Tests */
    1.12          ucx_test_register(suite, test_ucx_buffer_seektell);
     2.1 --- a/test/prop_tests.c	Fri Jul 12 20:50:18 2013 +0200
     2.2 +++ b/test/prop_tests.c	Sun Jul 14 17:11:34 2013 +0200
     2.3 @@ -43,7 +43,7 @@
     2.4  }
     2.5  
     2.6  UCX_TEST_IMPLEMENT(test_ucx_prop_parse) {  
     2.7 -    char *tests[] = {
     2.8 +    const char *tests[] = {
     2.9          "name = value\n",
    2.10          "name=value\n",
    2.11          "n=value\n",
    2.12 @@ -56,7 +56,7 @@
    2.13          "name = value\n\n"
    2.14      };
    2.15      
    2.16 -    char *names[] = {
    2.17 +    const char *names[] = {
    2.18          "name",
    2.19          "name",
    2.20          "n",
    2.21 @@ -69,7 +69,7 @@
    2.22          "name"
    2.23      };
    2.24      
    2.25 -    char *values[] = {
    2.26 +    const char *values[] = {
    2.27          "value",
    2.28          "value",
    2.29          "value",
    2.30 @@ -90,13 +90,13 @@
    2.31      for(int i=0;i<10;i++) {
    2.32          UcxPropParser *parser = ucx_prop_new();
    2.33          
    2.34 -        ucx_prop_fill(parser, tests[i], strlen(tests[i]));
    2.35 +        ucx_prop_fill(parser, (char*)tests[i], strlen(tests[i]));
    2.36          UCX_TEST_ASSERT(parser->buffer == tests[i], "fill failed");
    2.37          UCX_TEST_ASSERT(parser->buflen == strlen(tests[i]), "wrong buflen");
    2.38          
    2.39          int r = ucx_prop_parse(parser, &name, &value);
    2.40 -        sstr_t n = sstr(names[i]);
    2.41 -        sstr_t v = sstr(values[i]);
    2.42 +        sstr_t n = sstr((char*)names[i]);
    2.43 +        sstr_t v = sstr((char*)values[i]);
    2.44          UCX_TEST_ASSERT(r == 1, "parse returned 0");
    2.45          UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong property name");
    2.46          UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong property value");
    2.47 @@ -114,7 +114,7 @@
    2.48  }
    2.49  
    2.50  UCX_TEST_IMPLEMENT(test_ucx_prop_parse_multi) {
    2.51 -    char *names[] = {
    2.52 +    const char *names[] = {
    2.53          "a",
    2.54          "b",
    2.55          "c",
    2.56 @@ -125,7 +125,7 @@
    2.57          "key3"
    2.58      };
    2.59      
    2.60 -    char *values[] = {
    2.61 +    const char *values[] = {
    2.62          "a value",
    2.63          "b value",
    2.64          "core",
    2.65 @@ -136,7 +136,7 @@
    2.66          "value3"
    2.67      };
    2.68      
    2.69 -    char *str = "#\n"
    2.70 +    const char *str = "#\n"
    2.71          "# properties\n"
    2.72          "# contains key/value pairs\n"
    2.73          "#\n"
    2.74 @@ -157,15 +157,16 @@
    2.75      
    2.76      UCX_TEST_BEGIN
    2.77      
    2.78 -    ucx_prop_fill(parser, str, strlen(str));
    2.79 +    ucx_prop_fill(parser, (char*)str, strlen(str));
    2.80      
    2.81      sstr_t name;
    2.82      sstr_t value;
    2.83      for(int i=0;i<8;i++) {
    2.84          int r = ucx_prop_parse(parser, &name, &value);
    2.85          UCX_TEST_ASSERT(r == 1, "parse returned 0");
    2.86 -        UCX_TEST_ASSERT((!sstrcmp(name, sstr(names[i]))), "wrong name");
    2.87 -        UCX_TEST_ASSERT((!sstrcmp(value, sstr(values[i]))), "wrong value");
    2.88 +        UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)names[i]))), "wrong name");
    2.89 +        UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)values[i]))),
    2.90 +                "wrong value");
    2.91      }
    2.92      int r = ucx_prop_parse(parser, &name, &value);
    2.93      UCX_TEST_ASSERT(r == 0, "parse returned 1");
    2.94 @@ -177,7 +178,7 @@
    2.95  
    2.96  UCX_TEST_IMPLEMENT(test_ucx_prop_parse_part) {
    2.97      UcxPropParser *parser = ucx_prop_new();
    2.98 -    char *str;
    2.99 +    const char *str;
   2.100      int r;
   2.101      sstr_t name;
   2.102      sstr_t value;
   2.103 @@ -185,100 +186,100 @@
   2.104      UCX_TEST_BEGIN
   2.105      
   2.106      str = "";
   2.107 -    ucx_prop_fill(parser, str, strlen(str));
   2.108 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.109      r = ucx_prop_parse(parser, &name, &value);
   2.110      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.111      
   2.112      str = "  \n";
   2.113 -    ucx_prop_fill(parser, str, strlen(str));
   2.114 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.115      r = ucx_prop_parse(parser, &name, &value); 
   2.116      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.117      
   2.118      str = "name";
   2.119 -    ucx_prop_fill(parser, str, strlen(str));
   2.120 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.121      r = ucx_prop_parse(parser, &name, &value); 
   2.122      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.123      
   2.124      str = "    ";
   2.125 -    ucx_prop_fill(parser, str, strlen(str));
   2.126 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.127      r = ucx_prop_parse(parser, &name, &value); 
   2.128      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.129      
   2.130      str = "= ";
   2.131 -    ucx_prop_fill(parser, str, strlen(str));
   2.132 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.133      r = ucx_prop_parse(parser, &name, &value); 
   2.134      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.135      
   2.136      str = "value";
   2.137 -    ucx_prop_fill(parser, str, strlen(str));
   2.138 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.139      r = ucx_prop_parse(parser, &name, &value); 
   2.140      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.141      
   2.142      str = "\n";
   2.143 -    ucx_prop_fill(parser, str, strlen(str));
   2.144 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.145      r = ucx_prop_parse(parser, &name, &value); 
   2.146      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.147 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name");
   2.148 -    UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value");
   2.149 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name");
   2.150 +    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
   2.151      
   2.152      // second round
   2.153      str = "#comment\n";
   2.154 -    ucx_prop_fill(parser, str, strlen(str));
   2.155 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.156      r = ucx_prop_parse(parser, &name, &value); 
   2.157      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.158      
   2.159      str = "#comment\nname = ";
   2.160 -    ucx_prop_fill(parser, str, strlen(str));
   2.161 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.162      r = ucx_prop_parse(parser, &name, &value); 
   2.163      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.164      
   2.165      str = "value\na = b\n";
   2.166 -    ucx_prop_fill(parser, str, strlen(str));
   2.167 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.168      r = ucx_prop_parse(parser, &name, &value); 
   2.169      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.170 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name");
   2.171 -    UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value");
   2.172 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"name"))), "wrong name");
   2.173 +    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
   2.174      
   2.175      r = ucx_prop_parse(parser, &name, &value); 
   2.176      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.177 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name");
   2.178 -    UCX_TEST_ASSERT((!sstrcmp(value, sstr("b"))), "wrong value");
   2.179 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name");
   2.180 +    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"b"))), "wrong value");
   2.181      
   2.182      str = "# comment\n#\n#\ntests = ";
   2.183 -    ucx_prop_fill(parser, str, strlen(str));
   2.184 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.185      r = ucx_prop_parse(parser, &name, &value); 
   2.186      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.187      
   2.188      str = "test1 ";
   2.189 -    ucx_prop_fill(parser, str, strlen(str));
   2.190 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.191      r = ucx_prop_parse(parser, &name, &value); 
   2.192      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.193      
   2.194      str = "test2 test3 test4\n";
   2.195 -    sstr_t testv = sstr("test1 test2 test3 test4");
   2.196 -    ucx_prop_fill(parser, str, strlen(str));
   2.197 +    sstr_t testv = sstr((char*)"test1 test2 test3 test4");
   2.198 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.199      r = ucx_prop_parse(parser, &name, &value); 
   2.200      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.201 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("tests"))), "wrong name");
   2.202 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"tests"))), "wrong name");
   2.203      UCX_TEST_ASSERT((!sstrcmp(value, testv)), "wrong value");
   2.204      
   2.205      // test if parse finds a name/value after a tmp comment
   2.206      str = "# just a comment";
   2.207 -    ucx_prop_fill(parser, str, strlen(str));
   2.208 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.209      r = ucx_prop_parse(parser, &name, &value); 
   2.210      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.211      
   2.212      str = " in 3";
   2.213 -    ucx_prop_fill(parser, str, strlen(str));
   2.214 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.215      r = ucx_prop_parse(parser, &name, &value); 
   2.216      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.217      
   2.218      str = " parts\na = 1\n";
   2.219 -    ucx_prop_fill(parser, str, strlen(str));
   2.220 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.221      r = ucx_prop_parse(parser, &name, &value); 
   2.222      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.223 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name");
   2.224 -    UCX_TEST_ASSERT((!sstrcmp(value, sstr("1"))), "wrong value");
   2.225 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"a"))), "wrong name");
   2.226 +    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"1"))), "wrong value");
   2.227      
   2.228      UCX_TEST_END
   2.229      
   2.230 @@ -320,8 +321,8 @@
   2.231      r = ucx_prop_parse(parser, &name, &value);
   2.232      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.233      
   2.234 -    char *str = " = ";
   2.235 -    ucx_prop_fill(parser, str, strlen(str));
   2.236 +    const char *str = " = ";
   2.237 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.238      r = ucx_prop_parse(parser, &name, &value);
   2.239      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.240      
   2.241 @@ -338,7 +339,7 @@
   2.242      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.243      
   2.244      str = "\n#comment\nkey = value\n";
   2.245 -    ucx_prop_fill(parser, str, strlen(str));    
   2.246 +    ucx_prop_fill(parser, (char*)str, strlen(str));    
   2.247      r = ucx_prop_parse(parser, &name, &value);
   2.248      sstr_t n = sstrn(long_name, name_len);
   2.249      sstr_t v = sstrn(long_value, value_len);
   2.250 @@ -348,8 +349,8 @@
   2.251      
   2.252      r = ucx_prop_parse(parser, &name, &value);
   2.253      UCX_TEST_ASSERT(r == 1, "parse returned 0");
   2.254 -    UCX_TEST_ASSERT((!sstrcmp(name, sstr("key"))), "wrong name");
   2.255 -    UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value");
   2.256 +    UCX_TEST_ASSERT((!sstrcmp(name, sstr((char*)"key"))), "wrong name");
   2.257 +    UCX_TEST_ASSERT((!sstrcmp(value, sstr((char*)"value"))), "wrong value");
   2.258      
   2.259      r = ucx_prop_parse(parser, &name, &value);
   2.260      UCX_TEST_ASSERT(r == 0, "parse returned 1");
   2.261 @@ -360,3 +361,182 @@
   2.262      free(long_value);
   2.263      ucx_prop_free(parser);
   2.264  }
   2.265 +
   2.266 +UCX_TEST_IMPLEMENT(test_ucx_prop_parse2map) {
   2.267 +    UcxMap *map = ucx_map_new(16);
   2.268 +    UcxPropParser *parser = ucx_prop_new();
   2.269 +    
   2.270 +    UCX_TEST_BEGIN
   2.271 +    
   2.272 +    const char *str = "key1 = value1\nkey2 = value2\n\n#comment\n\nkey3 = value3\n";
   2.273 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.274 +    
   2.275 +    int r = ucx_prop_parse2map(parser, map);
   2.276 +    
   2.277 +    UCX_TEST_ASSERT(r == 0, "parse2map failed");
   2.278 +    UCX_TEST_ASSERT(map->count == 3, "wrong number of properties");
   2.279 +    
   2.280 +    char *v1 = (char*)ucx_map_cstr_get(map, "key1");
   2.281 +    char *v2 = (char*)ucx_map_cstr_get(map, "key2");
   2.282 +    char *v3 = (char*)ucx_map_cstr_get(map, "key3");
   2.283 +    
   2.284 +    UCX_TEST_ASSERT(v1, "value for key1 not found");
   2.285 +    UCX_TEST_ASSERT(v2, "value for key2 not found");
   2.286 +    UCX_TEST_ASSERT(v3, "value for key3 not found");
   2.287 +    
   2.288 +    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1");
   2.289 +    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2");
   2.290 +    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3");
   2.291 +    
   2.292 +    // second test
   2.293 +    ucx_map_free(map);
   2.294 +    free(v1);
   2.295 +    free(v2);
   2.296 +    free(v3);
   2.297 +    map = ucx_map_new(16);
   2.298 +    
   2.299 +    str = "\n#comment\n";
   2.300 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.301 +    
   2.302 +    r = ucx_prop_parse2map(parser, map);
   2.303 +    UCX_TEST_ASSERT(r == 0, "parse2map failed");
   2.304 +    UCX_TEST_ASSERT(map->count == 0, "wrong number of properties");
   2.305 +    
   2.306 +    str = "key1 = value1\nsyntax error line\n";
   2.307 +    ucx_prop_fill(parser, (char*)str, strlen(str));
   2.308 +    
   2.309 +    r = ucx_prop_parse2map(parser, map);
   2.310 +    UCX_TEST_ASSERT(r == 1, "parse2map should return 1");
   2.311 +    UCX_TEST_ASSERT(map->count == 1, "wrong number of properties");
   2.312 +    
   2.313 +    char *v = (char*)ucx_map_cstr_get(map, "key1");
   2.314 +    UCX_TEST_ASSERT((!strcmp(v, "value1")), "wrong value");
   2.315 +    
   2.316 +    UCX_TEST_END
   2.317 +    
   2.318 +    ucx_prop_free(parser);
   2.319 +}
   2.320 +
   2.321 +UCX_TEST_IMPLEMENT(test_ucx_properties_load) { 
   2.322 +    UCX_TEST_BEGIN
   2.323 +    FILE *f = tmpfile();
   2.324 +    UCX_TEST_ASSERT(f, "test file cannot be opened, test aborted");
   2.325 +    
   2.326 +    fprintf(f, "# properties file\n\nkey1 = value1\nkey2 = value2\n");
   2.327 +    fprintf(f, "\n\nkey3    = value3\n\n");
   2.328 +    
   2.329 +    size_t name_len = 512;
   2.330 +    char *long_name = (char*)malloc(name_len);
   2.331 +    memset(long_name, 'k', 512);
   2.332 +    
   2.333 +    size_t value_len = 2048;
   2.334 +    char *long_value = (char*)malloc(value_len);
   2.335 +    memset(long_value, 'v', 2048);
   2.336 +    
   2.337 +    fwrite(long_name, 1, name_len, f);
   2.338 +    fprintf(f, "    =    ");
   2.339 +    fwrite(long_value, 1, value_len, f);
   2.340 +    fprintf(f, "                         \n");
   2.341 +    
   2.342 +    fprintf(f, "\n\n\n\nlast_key = property value\n");
   2.343 +    
   2.344 +    fflush(f);
   2.345 +    fseek(f, 0, SEEK_SET);
   2.346 +    
   2.347 +    UcxMap *map = ucx_map_new(8);
   2.348 +    int r = ucx_properties_load(map, f);
   2.349 +    
   2.350 +    UCX_TEST_ASSERT(r == 0, "ucx_properties_load failed");
   2.351 +    UCX_TEST_ASSERT(map->count == 5, "wrong number of properties");
   2.352 +    
   2.353 +    char *v1 = (char*)ucx_map_cstr_get(map, "key1");
   2.354 +    char *v2 = (char*)ucx_map_cstr_get(map, "key2");
   2.355 +    char *v3 = (char*)ucx_map_cstr_get(map, "key3");
   2.356 +    char *lv = (char*)ucx_map_sstr_get(map, sstrn(long_name, name_len));
   2.357 +    char *lk = (char*)ucx_map_cstr_get(map, "last_key");
   2.358 +    
   2.359 +    UCX_TEST_ASSERT(v1, "value for key1 not found");
   2.360 +    UCX_TEST_ASSERT(v2, "value for key2 not found");
   2.361 +    UCX_TEST_ASSERT(v3, "value for key3 not found");
   2.362 +    UCX_TEST_ASSERT(lv, "value for long key not found");
   2.363 +    UCX_TEST_ASSERT(lk, "value for last_key not found");
   2.364 +    
   2.365 +    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value for key1");
   2.366 +    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value for key2");
   2.367 +    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value for key3");
   2.368 +    sstr_t long1 = sstrn(long_value, value_len);
   2.369 +    sstr_t long2 = sstr(lv);
   2.370 +    UCX_TEST_ASSERT((!sstrcmp(long1, long2)), "wrong value for long key");
   2.371 +    UCX_TEST_ASSERT(!strcmp(lk, "property value"), "wrong value for last_key");
   2.372 +    
   2.373 +    free(v1);
   2.374 +    free(v2);
   2.375 +    free(v3);
   2.376 +    free(lv);
   2.377 +    free(lk);
   2.378 +    ucx_map_free(map);
   2.379 +    fclose(f);
   2.380 +    
   2.381 +    UCX_TEST_END
   2.382 +}
   2.383 +
   2.384 +UCX_TEST_IMPLEMENT(test_ucx_properties_store) {
   2.385 +    UcxMap *map1 = ucx_map_new(16);
   2.386 +    ucx_map_cstr_put(map1, "key1", "value1");
   2.387 +    ucx_map_cstr_put(map1, "key2", "value2");
   2.388 +    ucx_map_cstr_put(map1, "key3", "value3");
   2.389 +    ucx_map_cstr_put(map1, "key4", "value4");
   2.390 +    ucx_map_cstr_put(map1, "property.key1", "some value 1");
   2.391 +    ucx_map_cstr_put(map1, "property.key2", "some value 2");
   2.392 +    ucx_map_cstr_put(map1, "property.key3", "some value 3");
   2.393 +    ucx_map_cstr_put(map1, "property.key4", "some value 4");
   2.394 +    
   2.395 +    UCX_TEST_BEGIN
   2.396 +    
   2.397 +    FILE *f = tmpfile();
   2.398 +    fprintf(f, "#\n# test property file\n#\n#\n");
   2.399 +    ucx_properties_store(map1, f);
   2.400 +    
   2.401 +    fflush(f);
   2.402 +    fseek(f, 0, SEEK_SET);
   2.403 +    UcxMap *map2 = ucx_map_new(16);
   2.404 +    ucx_properties_load(map2, f);
   2.405 +    
   2.406 +    UCX_TEST_ASSERT(map2->count == 8, "wrong number of properties in map2");
   2.407 +    
   2.408 +    char *v1 = (char*)ucx_map_cstr_get(map2, "key1");
   2.409 +    char *v2 = (char*)ucx_map_cstr_get(map2, "key2");
   2.410 +    char *v3 = (char*)ucx_map_cstr_get(map2, "key3");
   2.411 +    char *v4 = (char*)ucx_map_cstr_get(map2, "key4");
   2.412 +    char *v5 = (char*)ucx_map_cstr_get(map2, "property.key1");
   2.413 +    char *v6 = (char*)ucx_map_cstr_get(map2, "property.key2");
   2.414 +    char *v7 = (char*)ucx_map_cstr_get(map2, "property.key3");
   2.415 +    char *v8 = (char*)ucx_map_cstr_get(map2, "property.key4");
   2.416 +    
   2.417 +    UCX_TEST_ASSERT(v1 && v2 && v3 && v4 && v5 && v6 && v7 && v8,
   2.418 +            "missing values");
   2.419 +    
   2.420 +    UCX_TEST_ASSERT((!strcmp(v1, "value1")), "wrong value 1");
   2.421 +    UCX_TEST_ASSERT((!strcmp(v2, "value2")), "wrong value 2");
   2.422 +    UCX_TEST_ASSERT((!strcmp(v3, "value3")), "wrong value 3");
   2.423 +    UCX_TEST_ASSERT((!strcmp(v4, "value4")), "wrong value 4");
   2.424 +    UCX_TEST_ASSERT((!strcmp(v5, "some value 1")), "wrong value 5");
   2.425 +    UCX_TEST_ASSERT((!strcmp(v6, "some value 2")), "wrong value 6");
   2.426 +    UCX_TEST_ASSERT((!strcmp(v7, "some value 3")), "wrong value 7");
   2.427 +    UCX_TEST_ASSERT((!strcmp(v8, "some value 4")), "wrong value 8");
   2.428 +    
   2.429 +    free(v1);
   2.430 +    free(v2);
   2.431 +    free(v3);
   2.432 +    free(v4);
   2.433 +    free(v5);
   2.434 +    free(v6);
   2.435 +    free(v7);
   2.436 +    free(v8);
   2.437 +    ucx_map_free(map2);
   2.438 +    fclose(f);
   2.439 +    
   2.440 +    UCX_TEST_END
   2.441 +    
   2.442 +    ucx_map_free(map1);
   2.443 +}
     3.1 --- a/test/prop_tests.h	Fri Jul 12 20:50:18 2013 +0200
     3.2 +++ b/test/prop_tests.h	Sun Jul 14 17:11:34 2013 +0200
     3.3 @@ -41,6 +41,9 @@
     3.4  UCX_TEST_DECLARE(test_ucx_prop_parse_multi);
     3.5  UCX_TEST_DECLARE(test_ucx_prop_parse_part);
     3.6  UCX_TEST_DECLARE(test_ucx_prop_parse_long);
     3.7 +UCX_TEST_DECLARE(test_ucx_prop_parse2map);
     3.8 +UCX_TEST_DECLARE(test_ucx_properties_load);
     3.9 +UCX_TEST_DECLARE(test_ucx_properties_store);
    3.10  
    3.11  #ifdef	__cplusplus
    3.12  }
     4.1 --- a/ucx/map.h	Fri Jul 12 20:50:18 2013 +0200
     4.2 +++ b/ucx/map.h	Sun Jul 14 17:11:34 2013 +0200
     4.3 @@ -94,11 +94,11 @@
     4.4  void* ucx_map_remove(UcxMap *map, UcxKey key);
     4.5  
     4.6  #define ucx_map_sstr_put(m, s, d) \
     4.7 -    ucx_map_put(m, ucx_key(s.ptr, s.length), d)
     4.8 +    ucx_map_put(m, ucx_key(s.ptr, s.length), (void*)d)
     4.9  #define ucx_map_cstr_put(m, s, d) \
    4.10 -    ucx_map_put(m, ucx_key((void*)s, strlen(s)), d)
    4.11 +    ucx_map_put(m, ucx_key((void*)s, strlen(s)), (void*)d)
    4.12  #define ucx_map_int_put(m, i, d) \
    4.13 -    ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), d)
    4.14 +    ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), (void*)d)
    4.15  
    4.16  #define ucx_map_sstr_get(m, s) \
    4.17      ucx_map_get(m, ucx_key(s.ptr, s.length))
     5.1 --- a/ucx/properties.c	Fri Jul 12 20:50:18 2013 +0200
     5.2 +++ b/ucx/properties.c	Sun Jul 14 17:11:34 2013 +0200
     5.3 @@ -45,6 +45,7 @@
     5.4      parser->tmp = NULL;
     5.5      parser->tmplen = 0;
     5.6      parser->tmpcap = 0;
     5.7 +    parser->error = 0;
     5.8      parser->delimiter = '=';
     5.9      parser->comment1 = '#';
    5.10      parser->comment2 = 0;
    5.11 @@ -106,7 +107,7 @@
    5.12              parser->pos = newlen;
    5.13              
    5.14              /*
    5.15 -             * if ret == 0 the tmp buffer contained just space or comment
    5.16 +             * if ret == 0 the tmp buffer contained just space or a comment
    5.17               * we parse again with the original buffer to get a name/value
    5.18               * or a new tmp buffer
    5.19               */
    5.20 @@ -126,10 +127,7 @@
    5.21      char delimiter = parser->delimiter;
    5.22      
    5.23      // get one line and parse it
    5.24 -    while(1) {
    5.25 -        if(parser->pos >= parser->buflen) {
    5.26 -            return 0;
    5.27 -        }
    5.28 +    while(parser->pos < parser->buflen) {
    5.29          char *buf = parser->buffer + parser->pos;
    5.30          size_t len = parser->buflen - parser->pos;
    5.31          
    5.32 @@ -160,7 +158,7 @@
    5.33          }
    5.34  
    5.35          if(c != '\n') {
    5.36 -            // we have not enough data for a line
    5.37 +            // we don't have enough data for a line
    5.38              // store remaining bytes in temporary buffer for next round
    5.39              parser->tmpcap = len + 128;
    5.40              parser->tmp = (char*)malloc(parser->tmpcap);
    5.41 @@ -174,31 +172,96 @@
    5.42          if(delimiter_index == 0) {
    5.43              line = sstrtrim(line);
    5.44              if(line.length != 0) {
    5.45 -                // syntax error
    5.46 -                // TODO
    5.47 +                parser->error = 1;
    5.48              }
    5.49 -            parser->pos += i + 1;
    5.50 -            continue;
    5.51 +        } else {
    5.52 +            sstr_t n = sstrn(buf, delimiter_index);
    5.53 +            sstr_t v = sstrn(buf+delimiter_index+1, i-delimiter_index-1); 
    5.54 +            n = sstrtrim(n);
    5.55 +            v = sstrtrim(v);
    5.56 +            if(n.length != 0 || v.length != 0) {
    5.57 +                *name = n;
    5.58 +                *value = v;
    5.59 +                parser->pos += i + 1;
    5.60 +                return 1;
    5.61 +            } else {
    5.62 +                parser->error = 1;
    5.63 +            }
    5.64          }
    5.65          
    5.66 -        sstr_t n = sstrn(buf, delimiter_index);
    5.67 -        sstr_t v = sstrn(buf + delimiter_index + 1, i - delimiter_index - 1); 
    5.68 -        n = sstrtrim(n);
    5.69 -        v = sstrtrim(v);      
    5.70 -        if(n.length == 0 || v.length == 0) {
    5.71 -            // syntax error
    5.72 -            // TODO
    5.73 -            parser->pos += i + 1;
    5.74 -            continue;
    5.75 -        }
    5.76 -        
    5.77 -        *name = n;
    5.78 -        *value = v;
    5.79 -        
    5.80          parser->pos += i + 1;
    5.81 -        break;
    5.82      }
    5.83      
    5.84 -    return 1;
    5.85 +    return 0;
    5.86  }
    5.87  
    5.88 +int ucx_prop_parse2map(UcxPropParser *parser, UcxMap *map) {
    5.89 +    sstr_t name;
    5.90 +    sstr_t value;
    5.91 +    while(ucx_prop_parse(parser, &name, &value)) {
    5.92 +        name = sstrdup_alloc(map->allocator, name);
    5.93 +        if(!name.ptr) {
    5.94 +            return 1;
    5.95 +        }
    5.96 +        value = sstrdup_alloc(map->allocator, value);
    5.97 +        if(!value.ptr) {
    5.98 +            map->allocator->free(map->allocator->pool, value.ptr);
    5.99 +            return 1;
   5.100 +        }
   5.101 +        if(ucx_map_sstr_put(map, name, value.ptr)) {
   5.102 +            map->allocator->free(map->allocator->pool, name.ptr);
   5.103 +            map->allocator->free(map->allocator->pool, value.ptr);
   5.104 +            return 1;
   5.105 +        }
   5.106 +    }
   5.107 +    if(parser->error) {
   5.108 +        return 1;
   5.109 +    } else {
   5.110 +        return 0;
   5.111 +    }
   5.112 +}
   5.113 +
   5.114 +int ucx_properties_load(UcxMap *map, FILE *file) {
   5.115 +    UcxPropParser *parser = ucx_prop_new();
   5.116 +    if(!parser || !map || !file) {
   5.117 +        return 1;
   5.118 +    }
   5.119 +    
   5.120 +    int error = 0;
   5.121 +    size_t r;
   5.122 +    char buf[1024];
   5.123 +    while((r = fread(buf, 1, 1024, file)) != 0) {
   5.124 +        ucx_prop_fill(parser, buf, r);
   5.125 +        if(ucx_prop_parse2map(parser, map)) {
   5.126 +            error = 1;
   5.127 +            break;
   5.128 +        }
   5.129 +    }
   5.130 +    
   5.131 +    ucx_prop_free(parser);
   5.132 +    return error;
   5.133 +}
   5.134 +
   5.135 +int ucx_properties_store(UcxMap *map, FILE *file) {
   5.136 +    UcxMapIterator iter = ucx_map_iterator(map);
   5.137 +    char *k, *v;
   5.138 +    sstr_t key, value;
   5.139 +    size_t written;
   5.140 +
   5.141 +    UCX_MAP_FOREACH(v, iter) {
   5.142 +        k = (char*) iter.cur->key.data;
   5.143 +        key = sstrn(k, iter.cur->key.len);
   5.144 +        value = sstr(v);
   5.145 +
   5.146 +        written = 0;
   5.147 +        written += fwrite(key.ptr, 1, key.length, file);
   5.148 +        written += fwrite(" = ", 1, 3, file);
   5.149 +        written += fwrite(value.ptr, 1, value.length, file);
   5.150 +        written += fwrite("\n", 1, 1, file);
   5.151 +
   5.152 +        if (written != key.length + value.length + 4) return 1;
   5.153 +    }
   5.154 +
   5.155 +    return 0;
   5.156 +}
   5.157 +
     6.1 --- a/ucx/properties.h	Fri Jul 12 20:50:18 2013 +0200
     6.2 +++ b/ucx/properties.h	Sun Jul 14 17:11:34 2013 +0200
     6.3 @@ -43,6 +43,7 @@
     6.4      char   *tmp;
     6.5      size_t tmplen;
     6.6      size_t tmpcap;
     6.7 +    int    error;
     6.8      char   delimiter;
     6.9      char   comment1;
    6.10      char   comment2;
    6.11 @@ -54,6 +55,10 @@
    6.12  void ucx_prop_free(UcxPropParser *parser);
    6.13  void ucx_prop_fill(UcxPropParser *parser, char *buf, size_t len);
    6.14  int ucx_prop_parse(UcxPropParser *parser, sstr_t *name, sstr_t *value);
    6.15 +int ucx_prop_parse2map(UcxPropParser *parser, UcxMap *map);
    6.16 +
    6.17 +int ucx_properties_load(UcxMap *map, FILE *file);
    6.18 +int ucx_properties_store(UcxMap *map, FILE *file);
    6.19  
    6.20  #ifdef	__cplusplus
    6.21  }
     7.1 --- a/ucx/string.c	Fri Jul 12 20:50:18 2013 +0200
     7.2 +++ b/ucx/string.c	Sun Jul 14 17:11:34 2013 +0200
     7.3 @@ -31,6 +31,7 @@
     7.4  #include <stdarg.h>
     7.5  
     7.6  #include "string.h"
     7.7 +#include "allocator.h"
     7.8  
     7.9  sstr_t sstr(char *s) {
    7.10      sstr_t string;
    7.11 @@ -180,16 +181,30 @@
    7.12  sstr_t sstrdup(sstr_t s) {
    7.13      sstr_t newstring;
    7.14      newstring.ptr = (char*) malloc(s.length + 1);
    7.15 -    newstring.length = 0;
    7.16      if (newstring.ptr) {
    7.17          newstring.length = s.length;
    7.18          newstring.ptr[newstring.length] = 0;
    7.19 -
    7.20 +        
    7.21          memcpy(newstring.ptr, s.ptr, s.length);
    7.22      } else {
    7.23          newstring.length = 0;
    7.24      }
    7.25 +    
    7.26 +    return newstring;
    7.27 +}
    7.28  
    7.29 +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s) {
    7.30 +    sstr_t newstring;
    7.31 +    newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1);
    7.32 +    if (newstring.ptr) {
    7.33 +        newstring.length = s.length;
    7.34 +        newstring.ptr[newstring.length] = 0;
    7.35 +        
    7.36 +        memcpy(newstring.ptr, s.ptr, s.length);
    7.37 +    } else {
    7.38 +        newstring.length = 0;
    7.39 +    }
    7.40 +    
    7.41      return newstring;
    7.42  }
    7.43  
     8.1 --- a/ucx/string.h	Fri Jul 12 20:50:18 2013 +0200
     8.2 +++ b/ucx/string.h	Sun Jul 14 17:11:34 2013 +0200
     8.3 @@ -30,6 +30,7 @@
     8.4  #define	_SSTRING_H
     8.5  
     8.6  #include "ucx.h"
     8.7 +#include "allocator.h"
     8.8  #include <stddef.h>
     8.9  
    8.10  /* use macros for literals only */
    8.11 @@ -117,6 +118,7 @@
    8.12  int sstrcmp(sstr_t s1, sstr_t s2);
    8.13  
    8.14  sstr_t sstrdup(sstr_t s);
    8.15 +sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s);
    8.16  
    8.17  sstr_t sstrtrim(sstr_t string);
    8.18  

mercurial