Fri, 12 Jul 2013 20:50:18 +0200
new properties parser
g++-debug.mk | file | annotate | diff | comparison | revisions | |
gcc-debug.mk | file | annotate | diff | comparison | revisions | |
test/Makefile | file | annotate | diff | comparison | revisions | |
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/Makefile | file | annotate | diff | comparison | revisions | |
ucx/map.c | 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/g++-debug.mk Thu Jul 11 17:32:48 2013 +0200 1.2 +++ b/g++-debug.mk Fri Jul 12 20:50:18 2013 +0200 1.3 @@ -31,7 +31,7 @@ 1.4 AR = ar 1.5 RM = rm 1.6 1.7 -CFLAGS = -std=gnu++0x -g -O2 -fstrict-aliasing -Wall -pedantic -c 1.8 +CFLAGS = -std=gnu++0x -g -fstrict-aliasing -Wall -pedantic -c 1.9 COFLAGS = -o 1.10 LDFLAGS = 1.11 LOFLAGS = -o
2.1 --- a/gcc-debug.mk Thu Jul 11 17:32:48 2013 +0200 2.2 +++ b/gcc-debug.mk Fri Jul 12 20:50:18 2013 +0200 2.3 @@ -31,7 +31,7 @@ 2.4 AR = ar 2.5 RM = rm 2.6 2.7 -CFLAGS = -std=gnu99 -g -O2 -fstrict-aliasing -Wall -pedantic -c 2.8 +CFLAGS = -std=gnu99 -g -fstrict-aliasing -Wall -pedantic -c 2.9 COFLAGS = -o 2.10 LDFLAGS = 2.11 LOFLAGS = -o
3.1 --- a/test/Makefile Thu Jul 11 17:32:48 2013 +0200 3.2 +++ b/test/Makefile Fri Jul 12 20:50:18 2013 +0200 3.3 @@ -33,6 +33,7 @@ 3.4 SRC += dlist_tests.c 3.5 SRC += mpool_tests.c 3.6 SRC += map_tests.c 3.7 +SRC += prop_tests.c 3.8 SRC += string_tests.c 3.9 SRC += logging_tests.c 3.10 SRC += buffer_tests.c
4.1 --- a/test/main.c Thu Jul 11 17:32:48 2013 +0200 4.2 +++ b/test/main.c Fri Jul 12 20:50:18 2013 +0200 4.3 @@ -39,6 +39,7 @@ 4.4 #include "string_tests.h" 4.5 #include "mpool_tests.h" 4.6 #include "map_tests.h" 4.7 +#include "prop_tests.h" 4.8 #include "buffer_tests.h" 4.9 4.10 UCX_TEST_IMPLEMENT(testTestSuitePositive) { 4.11 @@ -168,8 +169,15 @@ 4.12 ucx_test_register(suite, test_ucx_map_store_load_with_mempool); 4.13 ucx_test_register(suite, test_ucx_map_clone); 4.14 ucx_test_register(suite, test_ucx_map_rehash); 4.15 - 4.16 - /* UcxMemstream Tests */ 4.17 + 4.18 + /* UcxPropertiesParser Tests */ 4.19 + ucx_test_register(suite, test_ucx_prop_new); 4.20 + ucx_test_register(suite, test_ucx_prop_parse); 4.21 + ucx_test_register(suite, test_ucx_prop_parse_multi); 4.22 + ucx_test_register(suite, test_ucx_prop_parse_part); 4.23 + ucx_test_register(suite, test_ucx_prop_parse_long); 4.24 + 4.25 + /* UcxBuffer Tests */ 4.26 ucx_test_register(suite, test_ucx_buffer_seektell); 4.27 ucx_test_register(suite, test_ucx_buffer_putc); 4.28 ucx_test_register(suite, test_ucx_buffer_putc_ax);
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/prop_tests.c Fri Jul 12 20:50:18 2013 +0200 5.3 @@ -0,0 +1,362 @@ 5.4 +/* 5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 5.6 + * 5.7 + * Copyright 2013 Olaf Wintermann. All rights reserved. 5.8 + * 5.9 + * Redistribution and use in source and binary forms, with or without 5.10 + * modification, are permitted provided that the following conditions are met: 5.11 + * 5.12 + * 1. Redistributions of source code must retain the above copyright 5.13 + * notice, this list of conditions and the following disclaimer. 5.14 + * 5.15 + * 2. Redistributions in binary form must reproduce the above copyright 5.16 + * notice, this list of conditions and the following disclaimer in the 5.17 + * documentation and/or other materials provided with the distribution. 5.18 + * 5.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 5.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 5.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5.29 + * POSSIBILITY OF SUCH DAMAGE. 5.30 + */ 5.31 + 5.32 +#include "prop_tests.h" 5.33 + 5.34 +UCX_TEST_IMPLEMENT(test_ucx_prop_new) { 5.35 + UcxPropParser *parser = ucx_prop_new(); 5.36 + 5.37 + UCX_TEST_BEGIN 5.38 + 5.39 + UCX_TEST_ASSERT(parser != NULL, "failed"); 5.40 + UCX_TEST_ASSERT(parser->buffer == NULL, "parser has buffer"); 5.41 + UCX_TEST_ASSERT(parser->tmp == NULL, "parser has tmp buffer"); 5.42 + 5.43 + UCX_TEST_END 5.44 + 5.45 + ucx_prop_free(parser); 5.46 +} 5.47 + 5.48 +UCX_TEST_IMPLEMENT(test_ucx_prop_parse) { 5.49 + char *tests[] = { 5.50 + "name = value\n", 5.51 + "name=value\n", 5.52 + "n=value\n", 5.53 + "name=v\n", 5.54 + "n=v\n", 5.55 + "name = value # comment\n", 5.56 + "#comment\nn=v\n", 5.57 + "# comment1\n# comment2\n\n \n\nname = value\n", 5.58 + " name = value\n", 5.59 + "name = value\n\n" 5.60 + }; 5.61 + 5.62 + char *names[] = { 5.63 + "name", 5.64 + "name", 5.65 + "n", 5.66 + "name", 5.67 + "n", 5.68 + "name", 5.69 + "n", 5.70 + "name", 5.71 + "name", 5.72 + "name" 5.73 + }; 5.74 + 5.75 + char *values[] = { 5.76 + "value", 5.77 + "value", 5.78 + "value", 5.79 + "v", 5.80 + "v", 5.81 + "value", 5.82 + "v", 5.83 + "value", 5.84 + "value", 5.85 + "value" 5.86 + }; 5.87 + 5.88 + UCX_TEST_BEGIN 5.89 + 5.90 + sstr_t name; 5.91 + sstr_t value; 5.92 + 5.93 + for(int i=0;i<10;i++) { 5.94 + UcxPropParser *parser = ucx_prop_new(); 5.95 + 5.96 + ucx_prop_fill(parser, tests[i], strlen(tests[i])); 5.97 + UCX_TEST_ASSERT(parser->buffer == tests[i], "fill failed"); 5.98 + UCX_TEST_ASSERT(parser->buflen == strlen(tests[i]), "wrong buflen"); 5.99 + 5.100 + int r = ucx_prop_parse(parser, &name, &value); 5.101 + sstr_t n = sstr(names[i]); 5.102 + sstr_t v = sstr(values[i]); 5.103 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.104 + UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong property name"); 5.105 + UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong property value"); 5.106 + 5.107 + r = ucx_prop_parse(parser, &name, &value); 5.108 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.109 + UCX_TEST_ASSERT(parser->tmp == NULL, "tmp not NULL"); 5.110 + UCX_TEST_ASSERT(parser->tmpcap == 0, "tmpcap not NULL"); 5.111 + UCX_TEST_ASSERT(parser->tmplen == 0, "tmplen not NULL"); 5.112 + 5.113 + ucx_prop_free(parser); 5.114 + } 5.115 + 5.116 + UCX_TEST_END 5.117 +} 5.118 + 5.119 +UCX_TEST_IMPLEMENT(test_ucx_prop_parse_multi) { 5.120 + char *names[] = { 5.121 + "a", 5.122 + "b", 5.123 + "c", 5.124 + "uap", 5.125 + "name", 5.126 + "key1", 5.127 + "key2", 5.128 + "key3" 5.129 + }; 5.130 + 5.131 + char *values[] = { 5.132 + "a value", 5.133 + "b value", 5.134 + "core", 5.135 + "core", 5.136 + "ucx", 5.137 + "value1", 5.138 + "value2", 5.139 + "value3" 5.140 + }; 5.141 + 5.142 + char *str = "#\n" 5.143 + "# properties\n" 5.144 + "# contains key/value pairs\n" 5.145 + "#\n" 5.146 + "a = a value\n" 5.147 + "b = b value\n" 5.148 + "c = core\n" 5.149 + "\n# test\n" 5.150 + "uap = core\n" 5.151 + "name = ucx\n" 5.152 + "# no = property\n" 5.153 + "key1 = value1\n" 5.154 + "#key1 = wrong value\n" 5.155 + "#key2 = not value 2\n" 5.156 + "key2 = value2\n" 5.157 + "\n\n\n \n key3=value3\n"; 5.158 + 5.159 + UcxPropParser *parser = ucx_prop_new(); 5.160 + 5.161 + UCX_TEST_BEGIN 5.162 + 5.163 + ucx_prop_fill(parser, str, strlen(str)); 5.164 + 5.165 + sstr_t name; 5.166 + sstr_t value; 5.167 + for(int i=0;i<8;i++) { 5.168 + int r = ucx_prop_parse(parser, &name, &value); 5.169 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.170 + UCX_TEST_ASSERT((!sstrcmp(name, sstr(names[i]))), "wrong name"); 5.171 + UCX_TEST_ASSERT((!sstrcmp(value, sstr(values[i]))), "wrong value"); 5.172 + } 5.173 + int r = ucx_prop_parse(parser, &name, &value); 5.174 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.175 + 5.176 + UCX_TEST_END 5.177 + 5.178 + ucx_prop_free(parser); 5.179 +} 5.180 + 5.181 +UCX_TEST_IMPLEMENT(test_ucx_prop_parse_part) { 5.182 + UcxPropParser *parser = ucx_prop_new(); 5.183 + char *str; 5.184 + int r; 5.185 + sstr_t name; 5.186 + sstr_t value; 5.187 + 5.188 + UCX_TEST_BEGIN 5.189 + 5.190 + str = ""; 5.191 + ucx_prop_fill(parser, str, strlen(str)); 5.192 + r = ucx_prop_parse(parser, &name, &value); 5.193 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.194 + 5.195 + str = " \n"; 5.196 + ucx_prop_fill(parser, str, strlen(str)); 5.197 + r = ucx_prop_parse(parser, &name, &value); 5.198 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.199 + 5.200 + str = "name"; 5.201 + ucx_prop_fill(parser, str, strlen(str)); 5.202 + r = ucx_prop_parse(parser, &name, &value); 5.203 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.204 + 5.205 + str = " "; 5.206 + ucx_prop_fill(parser, str, strlen(str)); 5.207 + r = ucx_prop_parse(parser, &name, &value); 5.208 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.209 + 5.210 + str = "= "; 5.211 + ucx_prop_fill(parser, str, strlen(str)); 5.212 + r = ucx_prop_parse(parser, &name, &value); 5.213 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.214 + 5.215 + str = "value"; 5.216 + ucx_prop_fill(parser, str, strlen(str)); 5.217 + r = ucx_prop_parse(parser, &name, &value); 5.218 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.219 + 5.220 + str = "\n"; 5.221 + ucx_prop_fill(parser, str, strlen(str)); 5.222 + r = ucx_prop_parse(parser, &name, &value); 5.223 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.224 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name"); 5.225 + UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); 5.226 + 5.227 + // second round 5.228 + str = "#comment\n"; 5.229 + ucx_prop_fill(parser, str, strlen(str)); 5.230 + r = ucx_prop_parse(parser, &name, &value); 5.231 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.232 + 5.233 + str = "#comment\nname = "; 5.234 + ucx_prop_fill(parser, str, strlen(str)); 5.235 + r = ucx_prop_parse(parser, &name, &value); 5.236 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.237 + 5.238 + str = "value\na = b\n"; 5.239 + ucx_prop_fill(parser, str, strlen(str)); 5.240 + r = ucx_prop_parse(parser, &name, &value); 5.241 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.242 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("name"))), "wrong name"); 5.243 + UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); 5.244 + 5.245 + r = ucx_prop_parse(parser, &name, &value); 5.246 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.247 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name"); 5.248 + UCX_TEST_ASSERT((!sstrcmp(value, sstr("b"))), "wrong value"); 5.249 + 5.250 + str = "# comment\n#\n#\ntests = "; 5.251 + ucx_prop_fill(parser, str, strlen(str)); 5.252 + r = ucx_prop_parse(parser, &name, &value); 5.253 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.254 + 5.255 + str = "test1 "; 5.256 + ucx_prop_fill(parser, str, strlen(str)); 5.257 + r = ucx_prop_parse(parser, &name, &value); 5.258 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.259 + 5.260 + str = "test2 test3 test4\n"; 5.261 + sstr_t testv = sstr("test1 test2 test3 test4"); 5.262 + ucx_prop_fill(parser, str, strlen(str)); 5.263 + r = ucx_prop_parse(parser, &name, &value); 5.264 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.265 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("tests"))), "wrong name"); 5.266 + UCX_TEST_ASSERT((!sstrcmp(value, testv)), "wrong value"); 5.267 + 5.268 + // test if parse finds a name/value after a tmp comment 5.269 + str = "# just a comment"; 5.270 + ucx_prop_fill(parser, str, strlen(str)); 5.271 + r = ucx_prop_parse(parser, &name, &value); 5.272 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.273 + 5.274 + str = " in 3"; 5.275 + ucx_prop_fill(parser, str, strlen(str)); 5.276 + r = ucx_prop_parse(parser, &name, &value); 5.277 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.278 + 5.279 + str = " parts\na = 1\n"; 5.280 + ucx_prop_fill(parser, str, strlen(str)); 5.281 + r = ucx_prop_parse(parser, &name, &value); 5.282 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.283 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("a"))), "wrong name"); 5.284 + UCX_TEST_ASSERT((!sstrcmp(value, sstr("1"))), "wrong value"); 5.285 + 5.286 + UCX_TEST_END 5.287 + 5.288 + ucx_prop_free(parser); 5.289 +} 5.290 + 5.291 +UCX_TEST_IMPLEMENT(test_ucx_prop_parse_long) { 5.292 + UcxPropParser *parser = ucx_prop_new(); 5.293 + int r; 5.294 + size_t name_len = 512; 5.295 + char *long_name = (char*)malloc(name_len); 5.296 + memset(long_name, 'a', 70); 5.297 + memset(long_name+70, 'b', 242); 5.298 + memset(long_name+312, 'c', 200); 5.299 + 5.300 + size_t value_len = 2048; 5.301 + char *long_value = (char*)malloc(value_len); 5.302 + memset(long_value, 'x', 1024); 5.303 + memset(long_value+1024, 'y', 1024); 5.304 + 5.305 + UCX_TEST_BEGIN 5.306 + 5.307 + sstr_t name; 5.308 + sstr_t value; 5.309 + 5.310 + ucx_prop_fill(parser, long_name, 10); 5.311 + r = ucx_prop_parse(parser, &name, &value); 5.312 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.313 + 5.314 + ucx_prop_fill(parser, long_name+10, 202); 5.315 + r = ucx_prop_parse(parser, &name, &value); 5.316 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.317 + 5.318 + ucx_prop_fill(parser, long_name+212, 200); 5.319 + r = ucx_prop_parse(parser, &name, &value); 5.320 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.321 + 5.322 + ucx_prop_fill(parser, long_name+412, 100); 5.323 + r = ucx_prop_parse(parser, &name, &value); 5.324 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.325 + 5.326 + char *str = " = "; 5.327 + ucx_prop_fill(parser, str, strlen(str)); 5.328 + r = ucx_prop_parse(parser, &name, &value); 5.329 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.330 + 5.331 + ucx_prop_fill(parser, long_value, 512); 5.332 + r = ucx_prop_parse(parser, &name, &value); 5.333 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.334 + 5.335 + ucx_prop_fill(parser, long_value+512, 1024); 5.336 + r = ucx_prop_parse(parser, &name, &value); 5.337 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.338 + 5.339 + ucx_prop_fill(parser, long_value+1536, 512); 5.340 + r = ucx_prop_parse(parser, &name, &value); 5.341 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.342 + 5.343 + str = "\n#comment\nkey = value\n"; 5.344 + ucx_prop_fill(parser, str, strlen(str)); 5.345 + r = ucx_prop_parse(parser, &name, &value); 5.346 + sstr_t n = sstrn(long_name, name_len); 5.347 + sstr_t v = sstrn(long_value, value_len); 5.348 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.349 + UCX_TEST_ASSERT((!sstrcmp(name, n)), "wrong name"); 5.350 + UCX_TEST_ASSERT((!sstrcmp(value, v)), "wrong value"); 5.351 + 5.352 + r = ucx_prop_parse(parser, &name, &value); 5.353 + UCX_TEST_ASSERT(r == 1, "parse returned 0"); 5.354 + UCX_TEST_ASSERT((!sstrcmp(name, sstr("key"))), "wrong name"); 5.355 + UCX_TEST_ASSERT((!sstrcmp(value, sstr("value"))), "wrong value"); 5.356 + 5.357 + r = ucx_prop_parse(parser, &name, &value); 5.358 + UCX_TEST_ASSERT(r == 0, "parse returned 1"); 5.359 + 5.360 + UCX_TEST_END 5.361 + 5.362 + free(long_name); 5.363 + free(long_value); 5.364 + ucx_prop_free(parser); 5.365 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/prop_tests.h Fri Jul 12 20:50:18 2013 +0200 6.3 @@ -0,0 +1,50 @@ 6.4 +/* 6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 6.6 + * 6.7 + * Copyright 2013 Olaf Wintermann. All rights reserved. 6.8 + * 6.9 + * Redistribution and use in source and binary forms, with or without 6.10 + * modification, are permitted provided that the following conditions are met: 6.11 + * 6.12 + * 1. Redistributions of source code must retain the above copyright 6.13 + * notice, this list of conditions and the following disclaimer. 6.14 + * 6.15 + * 2. Redistributions in binary form must reproduce the above copyright 6.16 + * notice, this list of conditions and the following disclaimer in the 6.17 + * documentation and/or other materials provided with the distribution. 6.18 + * 6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.29 + * POSSIBILITY OF SUCH DAMAGE. 6.30 + */ 6.31 + 6.32 +#ifndef PROP_TESTS_H 6.33 +#define PROP_TESTS_H 6.34 + 6.35 +#include "ucx/test.h" 6.36 +#include "ucx/properties.h" 6.37 + 6.38 +#ifdef __cplusplus 6.39 +extern "C" { 6.40 +#endif 6.41 + 6.42 +UCX_TEST_DECLARE(test_ucx_prop_new); 6.43 +UCX_TEST_DECLARE(test_ucx_prop_parse); 6.44 +UCX_TEST_DECLARE(test_ucx_prop_parse_multi); 6.45 +UCX_TEST_DECLARE(test_ucx_prop_parse_part); 6.46 +UCX_TEST_DECLARE(test_ucx_prop_parse_long); 6.47 + 6.48 +#ifdef __cplusplus 6.49 +} 6.50 +#endif 6.51 + 6.52 +#endif /* PROP_TESTS_H */ 6.53 +
7.1 --- a/ucx/Makefile Thu Jul 11 17:32:48 2013 +0200 7.2 +++ b/ucx/Makefile Fri Jul 12 20:50:18 2013 +0200 7.3 @@ -33,6 +33,7 @@ 7.4 SRC += list.c 7.5 SRC += dlist.c 7.6 SRC += map.c 7.7 +SRC += properties.c 7.8 SRC += mempool.c 7.9 SRC += string.c 7.10 SRC += test.c
8.1 --- a/ucx/map.c Thu Jul 11 17:32:48 2013 +0200 8.2 +++ b/ucx/map.c Fri Jul 12 20:50:18 2013 +0200 8.3 @@ -39,7 +39,7 @@ 8.4 if(size == 0) { 8.5 size = 16; 8.6 } 8.7 - 8.8 + 8.9 if(!allocator) { 8.10 allocator = ucx_default_allocator(); 8.11 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/ucx/properties.c Fri Jul 12 20:50:18 2013 +0200 9.3 @@ -0,0 +1,204 @@ 9.4 +/* 9.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 9.6 + * 9.7 + * Copyright 2013 Olaf Wintermann. All rights reserved. 9.8 + * 9.9 + * Redistribution and use in source and binary forms, with or without 9.10 + * modification, are permitted provided that the following conditions are met: 9.11 + * 9.12 + * 1. Redistributions of source code must retain the above copyright 9.13 + * notice, this list of conditions and the following disclaimer. 9.14 + * 9.15 + * 2. Redistributions in binary form must reproduce the above copyright 9.16 + * notice, this list of conditions and the following disclaimer in the 9.17 + * documentation and/or other materials provided with the distribution. 9.18 + * 9.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 9.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 9.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 9.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 9.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 9.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 9.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 9.29 + * POSSIBILITY OF SUCH DAMAGE. 9.30 + */ 9.31 + 9.32 +#include <stdio.h> 9.33 +#include <stdlib.h> 9.34 +#include <string.h> 9.35 + 9.36 +#include "properties.h" 9.37 + 9.38 +UcxPropParser *ucx_prop_new() { 9.39 + UcxPropParser *parser = (UcxPropParser*)malloc( 9.40 + sizeof(UcxPropParser)); 9.41 + if(!parser) { 9.42 + return NULL; 9.43 + } 9.44 + 9.45 + parser->buffer = NULL; 9.46 + parser->buflen = 0; 9.47 + parser->pos = 0; 9.48 + parser->tmp = NULL; 9.49 + parser->tmplen = 0; 9.50 + parser->tmpcap = 0; 9.51 + parser->delimiter = '='; 9.52 + parser->comment1 = '#'; 9.53 + parser->comment2 = 0; 9.54 + parser->comment3 = 0; 9.55 + 9.56 + return parser; 9.57 +} 9.58 + 9.59 +void ucx_prop_free(UcxPropParser *parser) { 9.60 + if(parser->tmp) { 9.61 + free(parser->tmp); 9.62 + } 9.63 + free(parser); 9.64 +} 9.65 + 9.66 +void ucx_prop_fill(UcxPropParser *parser, char *buf, size_t len) { 9.67 + parser->buffer = buf; 9.68 + parser->buflen = len; 9.69 + parser->pos = 0; 9.70 +} 9.71 + 9.72 +static void parser_tmp_append(UcxPropParser *parser, char *buf, size_t len) { 9.73 + if(parser->tmpcap - parser->tmplen < len) { 9.74 + size_t newcap = parser->tmpcap + len + 64; 9.75 + parser->tmp = (char*)realloc(parser->tmp, newcap); 9.76 + parser->tmpcap = newcap; 9.77 + } 9.78 + memcpy(parser->tmp + parser->tmplen, buf, len); 9.79 + parser->tmplen += len; 9.80 +} 9.81 + 9.82 +int ucx_prop_parse(UcxPropParser *parser, sstr_t *name, sstr_t *value) { 9.83 + if(parser->tmplen > 0) { 9.84 + char *buf = parser->buffer + parser->pos; 9.85 + size_t len = parser->buflen - parser->pos; 9.86 + sstr_t str = sstrn(buf, len); 9.87 + sstr_t nl = sstrchr(str, '\n'); 9.88 + if(nl.ptr) { 9.89 + size_t newlen = (size_t)(nl.ptr - buf) + 1; 9.90 + parser_tmp_append(parser, buf, newlen); 9.91 + // the tmp buffer contains exactly one line now 9.92 + 9.93 + char *orig_buf = parser->buffer; 9.94 + size_t orig_len = parser->buflen; 9.95 + 9.96 + parser->buffer = parser->tmp; 9.97 + parser->buflen = parser->tmplen; 9.98 + parser->pos = 0; 9.99 + parser->tmp = NULL; 9.100 + parser->tmpcap = 0; 9.101 + parser->tmplen = 0; 9.102 + // run parse with the tmp buffer as main buffer 9.103 + int ret = ucx_prop_parse(parser, name, value); 9.104 + 9.105 + // restore original buffer 9.106 + parser->tmp = parser->buffer; 9.107 + parser->buffer = orig_buf; 9.108 + parser->buflen = orig_len; 9.109 + parser->pos = newlen; 9.110 + 9.111 + /* 9.112 + * if ret == 0 the tmp buffer contained just space or comment 9.113 + * we parse again with the original buffer to get a name/value 9.114 + * or a new tmp buffer 9.115 + */ 9.116 + return ret ? ret : ucx_prop_parse(parser, name, value); 9.117 + } else { 9.118 + parser_tmp_append(parser, buf, len); 9.119 + return 0; 9.120 + } 9.121 + } else if(parser->tmp) { 9.122 + free(parser->tmp); 9.123 + parser->tmp = NULL; 9.124 + } 9.125 + 9.126 + char comment1 = parser->comment1; 9.127 + char comment2 = parser->comment2; 9.128 + char comment3 = parser->comment3; 9.129 + char delimiter = parser->delimiter; 9.130 + 9.131 + // get one line and parse it 9.132 + while(1) { 9.133 + if(parser->pos >= parser->buflen) { 9.134 + return 0; 9.135 + } 9.136 + char *buf = parser->buffer + parser->pos; 9.137 + size_t len = parser->buflen - parser->pos; 9.138 + 9.139 + /* 9.140 + * First we check if we have at least one line. We also get indices of 9.141 + * delimiter and comment chars 9.142 + */ 9.143 + size_t delimiter_index = 0; 9.144 + size_t comment_index = 0; 9.145 + int has_comment = 0; 9.146 + 9.147 + size_t i = 0; 9.148 + char c = 0; 9.149 + for(;i<len;i++) { 9.150 + c = buf[i]; 9.151 + if(c == comment1 || c == comment2 || c == comment3) { 9.152 + if(comment_index == 0) { 9.153 + comment_index = i; 9.154 + has_comment = 1; 9.155 + } 9.156 + } else if(c == delimiter) { 9.157 + if(delimiter_index == 0 && !has_comment) { 9.158 + delimiter_index = i; 9.159 + } 9.160 + } else if(c == '\n') { 9.161 + break; 9.162 + } 9.163 + } 9.164 + 9.165 + if(c != '\n') { 9.166 + // we have not enough data for a line 9.167 + // store remaining bytes in temporary buffer for next round 9.168 + parser->tmpcap = len + 128; 9.169 + parser->tmp = (char*)malloc(parser->tmpcap); 9.170 + parser->tmplen = len; 9.171 + memcpy(parser->tmp, buf, len); 9.172 + return 0; 9.173 + } 9.174 + 9.175 + sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i); 9.176 + // check line 9.177 + if(delimiter_index == 0) { 9.178 + line = sstrtrim(line); 9.179 + if(line.length != 0) { 9.180 + // syntax error 9.181 + // TODO 9.182 + } 9.183 + parser->pos += i + 1; 9.184 + continue; 9.185 + } 9.186 + 9.187 + sstr_t n = sstrn(buf, delimiter_index); 9.188 + sstr_t v = sstrn(buf + delimiter_index + 1, i - delimiter_index - 1); 9.189 + n = sstrtrim(n); 9.190 + v = sstrtrim(v); 9.191 + if(n.length == 0 || v.length == 0) { 9.192 + // syntax error 9.193 + // TODO 9.194 + parser->pos += i + 1; 9.195 + continue; 9.196 + } 9.197 + 9.198 + *name = n; 9.199 + *value = v; 9.200 + 9.201 + parser->pos += i + 1; 9.202 + break; 9.203 + } 9.204 + 9.205 + return 1; 9.206 +} 9.207 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/ucx/properties.h Fri Jul 12 20:50:18 2013 +0200 10.3 @@ -0,0 +1,63 @@ 10.4 +/* 10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 10.6 + * 10.7 + * Copyright 2013 Olaf Wintermann. All rights reserved. 10.8 + * 10.9 + * Redistribution and use in source and binary forms, with or without 10.10 + * modification, are permitted provided that the following conditions are met: 10.11 + * 10.12 + * 1. Redistributions of source code must retain the above copyright 10.13 + * notice, this list of conditions and the following disclaimer. 10.14 + * 10.15 + * 2. Redistributions in binary form must reproduce the above copyright 10.16 + * notice, this list of conditions and the following disclaimer in the 10.17 + * documentation and/or other materials provided with the distribution. 10.18 + * 10.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 10.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 10.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10.29 + * POSSIBILITY OF SUCH DAMAGE. 10.30 + */ 10.31 + 10.32 +#ifndef PROPERTIES_H 10.33 +#define PROPERTIES_H 10.34 + 10.35 +#include "ucx.h" 10.36 +#include "map.h" 10.37 + 10.38 +#ifdef __cplusplus 10.39 +extern "C" { 10.40 +#endif 10.41 + 10.42 +typedef struct { 10.43 + char *buffer; 10.44 + size_t buflen; 10.45 + size_t pos; 10.46 + char *tmp; 10.47 + size_t tmplen; 10.48 + size_t tmpcap; 10.49 + char delimiter; 10.50 + char comment1; 10.51 + char comment2; 10.52 + char comment3; 10.53 +} UcxPropParser; 10.54 + 10.55 + 10.56 +UcxPropParser *ucx_prop_new(); 10.57 +void ucx_prop_free(UcxPropParser *parser); 10.58 +void ucx_prop_fill(UcxPropParser *parser, char *buf, size_t len); 10.59 +int ucx_prop_parse(UcxPropParser *parser, sstr_t *name, sstr_t *value); 10.60 + 10.61 +#ifdef __cplusplus 10.62 +} 10.63 +#endif 10.64 + 10.65 +#endif /* PROPERTIES_H */ 10.66 +
11.1 --- a/ucx/string.c Thu Jul 11 17:32:48 2013 +0200 11.2 +++ b/ucx/string.c Fri Jul 12 20:50:18 2013 +0200 11.3 @@ -106,6 +106,18 @@ 11.4 return new_sstr; 11.5 } 11.6 11.7 +sstr_t sstrchr(sstr_t s, int c) { 11.8 + for(size_t i=0;i<s.length;i++) { 11.9 + if(s.ptr[i] == c) { 11.10 + return sstrsubs(s, i); 11.11 + } 11.12 + } 11.13 + sstr_t n; 11.14 + n.ptr = NULL; 11.15 + n.length = 0; 11.16 + return n; 11.17 +} 11.18 + 11.19 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { 11.20 if (d.length == 0) { 11.21 return NULL;
12.1 --- a/ucx/string.h Thu Jul 11 17:32:48 2013 +0200 12.2 +++ b/ucx/string.h Fri Jul 12 20:50:18 2013 +0200 12.3 @@ -92,6 +92,11 @@ 12.4 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length); 12.5 12.6 /* 12.7 + * 12.8 + */ 12.9 +sstr_t sstrchr(sstr_t s, int c); 12.10 + 12.11 +/* 12.12 * splits s into n parts 12.13 * 12.14 * s the string to split