1.1 --- a/docs/src/modules-ucx2.md Sun Nov 20 17:48:42 2022 +0100 1.2 +++ b/docs/src/modules-ucx2.md Sun Nov 20 21:08:36 2022 +0100 1.3 @@ -75,20 +75,20 @@ 1.4 return result; 1.5 } 1.6 1.7 -/* ... */ 1.8 +// ... 1.9 1.10 -sstr_t* array = /* some standard array of strings */ 1.11 -size_t arrlen = /* the length of the array */ 1.12 +sstr_t* array = // some standard array of strings 1.13 +size_t arrlen = // the length of the array 1.14 1.15 UcxArray* result = create_unique(array,arrlen); 1.16 1.17 -/* Iterate over the array and print the elements */ 1.18 +// Iterate over the array and print the elements 1.19 sstr_t* unique = result->data; 1.20 for (size_t i = 0 ; i < result->size ; i++) { 1.21 printf("%" PRIsstr "\n", SFMT(unique[i])); 1.22 } 1.23 1.24 -/* Free the array. */ 1.25 +// Free the array. 1.26 ucx_array_free(result); 1.27 ``` 1.28 ### Preventing out of bounds writes 1.29 @@ -128,23 +128,18 @@ 1.30 is to find all items within a time window `[t_start, t_end]`. 1.31 With AVL Trees this is easy: 1.32 ```C 1.33 -/* --------------------- 1.34 - * Somewhere in a header 1.35 - */ 1.36 +// Somewhere in a header 1.37 typedef struct { 1.38 time_t ts; 1.39 - /* other important data */ 1.40 + // other important data 1.41 } MyObject; 1.42 1.43 -/* ----------- 1.44 - * Source code 1.45 - */ 1.46 +// Source code 1.47 +UcxAVLTree* tree = ucx_avl_new(ucx_cmp_longint); 1.48 +// ... populate tree with objects, use '& MyObject.ts' as key ... 1.49 1.50 -UcxAVLTree* tree = ucx_avl_new(ucx_cmp_longint); 1.51 -/* ... populate tree with objects, use '& MyObject.ts' as key ... */ 1.52 1.53 - 1.54 -/* Now find every item, with 30 <= ts <= 70 */ 1.55 +// Now find every item, with 30 <= ts <= 70 1.56 time_t ts_start = 30; 1.57 time_t ts_end = 70; 1.58 1.59 @@ -212,18 +207,18 @@ 1.60 1.61 UcxBuffer* linebuf = 1.62 ucx_buffer_new( 1.63 - NULL, /* the buffer should manage the memory area for us */ 1.64 - 2*chunksize, /* initial size should be twice the chunk size */ 1.65 - UCX_BUFFER_AUTOEXTEND); /* the buffer will grow when necessary */ 1.66 + NULL, // the buffer should manage the memory area for us 1.67 + 2*chunksize, // initial size should be twice the chunk size 1.68 + UCX_BUFFER_AUTOEXTEND); // the buffer will grow when necessary 1.69 1.70 size_t lineno = 1; 1.71 do { 1.72 - /* read line chunk */ 1.73 + // read line chunk 1.74 size_t read = ucx_stream_ncopy( 1.75 input, linebuf, fread, ucx_buffer_write, chunksize); 1.76 if (read == 0) break; 1.77 1.78 - /* handle line endings */ 1.79 + // handle line endings 1.80 do { 1.81 sstr_t bufstr = ucx_buffer_to_sstr(linebuf); 1.82 sstr_t nl = sstrchr(bufstr, '\n'); 1.83 @@ -234,13 +229,13 @@ 1.84 1.85 printf("%zu: %" PRIsstr "\n", lineno++, SFMT(linestr)); 1.86 1.87 - /* shift the buffer to the next line */ 1.88 + // shift the buffer to the next line 1.89 ucx_buffer_shift_left(linebuf, linelen+1); 1.90 } while(1); 1.91 1.92 } while(1); 1.93 1.94 - /* print the 'noeol' line, if any */ 1.95 + // print the 'noeol' line, if any 1.96 sstr_t lastline = ucx_buffer_to_sstr(linebuf); 1.97 if (lastline.length > 0) { 1.98 printf("%zu: %" PRIsstr, lineno, SFMT(lastline)); 1.99 @@ -286,27 +281,27 @@ 1.100 return list; 1.101 } 1.102 1.103 -/* we will need this function to clean up the list contents later */ 1.104 +// we will need this function to clean up the list contents later 1.105 void free_sstr(void* ptr) { 1.106 sstr_t* s = ptr; 1.107 free(s->ptr); 1.108 free(s); 1.109 } 1.110 1.111 -/* ... */ 1.112 +// ... 1.113 1.114 -sstr_t* array = /* some array of strings */ 1.115 -size_t arrlen = /* the length of the array */ 1.116 +sstr_t* array = // some array of strings 1.117 +size_t arrlen = // the length of the array 1.118 1.119 UcxList* list = remove_duplicates(array,arrlen); 1.120 1.121 -/* Iterate over the list and print the elements */ 1.122 +// Iterate over the list and print the elements 1.123 UCX_FOREACH(elem, list) { 1.124 sstr_t s = *((sstr_t*)elem->data); 1.125 printf("%" PRIsstr "\n", SFMT(s)); 1.126 } 1.127 1.128 -/* Use our free function to free the duplicated strings. */ 1.129 +// Use our free function to free the duplicated strings. 1.130 ucx_list_free_content(list, free_sstr); 1.131 ucx_list_free(list); 1.132 ``` 1.133 @@ -392,7 +387,7 @@ 1.134 ucx_map_cstr_put(options, option, arg); 1.135 option = NULL; 1.136 } else { 1.137 - /* ... handle argument that is not an option ... */ 1.138 + // ... handle argument that is not an option ... 1.139 } 1.140 } 1.141 if(option) { 1.142 @@ -463,20 +458,20 @@ 1.143 perror("Cannot open file"); 1.144 return 1; 1.145 } 1.146 - /* close the file automatically at pool destruction*/ 1.147 + // close the file automatically at pool destruction 1.148 ucx_mempool_reg_destr(pool, f, (ucx_destructor) fclose); 1.149 1.150 - /* create a buffer and register it at the memory pool for destruction */ 1.151 + // create a buffer and register it at the memory pool for destruction 1.152 UcxBuffer* content = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); 1.153 ucx_mempool_reg_destr(pool, content, (ucx_destructor) ucx_buffer_free); 1.154 1.155 - /* read the file and split it by lines first */ 1.156 + // read the file and split it by lines first 1.157 ucx_stream_copy(f, content, fread, ucx_buffer_write); 1.158 sstr_t contentstr = ucx_buffer_to_sstr(content); 1.159 ssize_t lc = 0; 1.160 sstr_t* lines = sstrsplit_a(pool->allocator, contentstr, S("\n"), &lc); 1.161 1.162 - /* skip the header and parse the remaining data */ 1.163 + // skip the header and parse the remaining data 1.164 UcxList* datalist = NULL; 1.165 for (size_t i = 1 ; i < lc ; i++) { 1.166 if (lines[i].length == 0) continue; 1.167 @@ -494,7 +489,7 @@ 1.168 datalist = ucx_list_append_a(pool->allocator, datalist, data); 1.169 } 1.170 1.171 - /* control output */ 1.172 + // control output 1.173 UCX_FOREACH(elem, datalist) { 1.174 CSVData* data = elem->data; 1.175 printf("Column A: %" PRIsstr " | " 1.176 @@ -504,7 +499,7 @@ 1.177 ); 1.178 } 1.179 1.180 - /* cleanup everything, no manual free() needed */ 1.181 + // cleanup everything, no manual free() needed 1.182 ucx_mempool_destroy(pool); 1.183 1.184 return 0; 1.185 @@ -519,10 +514,10 @@ 1.186 ```C 1.187 MyObject* obj = ucx_mempool_malloc(pool, sizeof(MyObject)); 1.188 1.189 - /* some special initialization with own resource management */ 1.190 + // some special initialization with own resource management 1.191 my_object_init(obj); 1.192 1.193 - /* register destructor function */ 1.194 + // register destructor function 1.195 ucx_mempool_set_destr(obj, (ucx_destructor) my_object_destroy); 1.196 ``` 1.197 Be aware, that your destructor function should not free any memory, that is 1.198 @@ -544,30 +539,30 @@ 1.199 ### Example: Loading properties from a file 1.200 1.201 ```C 1.202 -/* Open the file as usual */ 1.203 +// Open the file as usual 1.204 FILE* file = fopen("myprops.properties", "r"); 1.205 if (!file) { 1.206 // error handling 1.207 return 1; 1.208 } 1.209 1.210 -/* Load the properties from the file */ 1.211 +// Load the properties from the file 1.212 UcxMap* myprops = ucx_map_new(16); 1.213 if (ucx_properties_load(myprops, file)) { 1.214 - /* ... error handling ... */ 1.215 + // ... error handling ... 1.216 fclose(file); 1.217 ucx_map_free(myprops); 1.218 return 1; 1.219 } 1.220 1.221 -/* Print out the key/value pairs */ 1.222 +// Print out the key/value pairs 1.223 char* propval; 1.224 UcxMapIterator propiter = ucx_map_iterator(myprops); 1.225 UCX_MAP_FOREACH(key, propval, propiter) { 1.226 printf("%s = %s\n", (char*)key.data, propval); 1.227 } 1.228 1.229 -/* Don't forget to free the values before freeing the map */ 1.230 +// Don't forget to free the values before freeing the map 1.231 ucx_map_free_content(myprops, NULL); 1.232 ucx_map_free(myprops); 1.233 fclose(file); 1.234 @@ -599,30 +594,30 @@ 1.235 const char* str = "Hello!"; 1.236 size_t strn = 7; 1.237 1.238 - /* push the integer */ 1.239 + // push the integer 1.240 ucx_stack_push(&stack, sizeof(int), &i); 1.241 1.242 - /* push the float and rember the address */ 1.243 + // push the float and rember the address 1.244 float* remember = ucx_stack_push(&stack, sizeof(float), &f); 1.245 1.246 - /* push the string with zero terminator */ 1.247 + // push the string with zero terminator 1.248 ucx_stack_push(&stack, strn, str); 1.249 1.250 - /* if we forget, how big an element was, we can ask the stack */ 1.251 + // if we forget, how big an element was, we can ask the stack 1.252 printf("Length of string: %zu\n", ucx_stack_topsize(&stack)-1); 1.253 1.254 - /* retrieve the string as sstr_t, without zero terminator! */ 1.255 + // retrieve the string as sstr_t, without zero terminator! 1.256 sstr_t s; 1.257 s.length = ucx_stack_topsize(&stack)-1; 1.258 s.ptr = malloc(s.length); 1.259 ucx_stack_popn(&stack, s.ptr, s.length); 1.260 printf("%" PRIsstr "\n", SFMT(s)); 1.261 1.262 - /* print the float directly from the stack and free it */ 1.263 + // print the float directly from the stack and free it 1.264 printf("Float: %f\n", *remember); 1.265 ucx_stack_free(&stack, remember); 1.266 1.267 - /* the last element is the integer */ 1.268 + // the last element is the integer 1.269 int j; 1.270 ucx_stack_pop(&stack, &j); 1.271 printf("Integer: %d\n", j); 1.272 @@ -647,21 +642,21 @@ 1.273 There are several ways to create an `sstr_t`: 1.274 1.275 ```C 1.276 -/* (1) sstr() uses strlen() internally, hence cstr MUST be zero-terminated */ 1.277 +// (1) sstr() uses strlen() internally, hence cstr MUST be zero-terminated 1.278 sstr_t a = sstr(cstr); 1.279 1.280 -/* (2) cstr does not need to be zero-terminated, if length is specified */ 1.281 +// (2) cstr does not need to be zero-terminated, if length is specified 1.282 sstr_t b = sstrn(cstr, len); 1.283 1.284 -/* (3) S() macro creates sstr_t from a string using sizeof() and using sstrn(). 1.285 - This version is especially useful for function arguments */ 1.286 +// (3) S() macro creates sstr_t from a string using sizeof() and using sstrn(). 1.287 +// This version is especially useful for function arguments 1.288 sstr_t c = S("hello"); 1.289 1.290 -/* (4) SC() macro works like S(), but makes the string immutable using scstr_t. 1.291 - (available since UCX 2.0) */ 1.292 +// (4) SC() macro works like S(), but makes the string immutable using scstr_t. 1.293 +// (available since UCX 2.0) 1.294 scstr_t d = SC("hello"); 1.295 1.296 -/* (5) ST() macro creates sstr_t struct literal using sizeof() */ 1.297 +// (5) ST() macro creates sstr_t struct literal using sizeof() 1.298 sstr_t e = ST("hello"); 1.299 ``` 1.300 1.301 @@ -716,12 +711,12 @@ 1.302 sstr_t test = ST("here::are::some::strings"); 1.303 sstr_t delim = ST("::"); 1.304 1.305 -ssize_t count = 0; /* no limit */ 1.306 +ssize_t count = 0; // no limit 1.307 UcxMempool* pool = ucx_mempool_new_default(); 1.308 1.309 sstr_t* result = sstrsplit_a(pool->allocator, test, delim, &count); 1.310 for (ssize_t i = 0 ; i < count ; i++) { 1.311 - /* don't forget to specify the length via the %*s format specifier */ 1.312 + // don't forget to specify the length via the %*s format specifier 1.313 printf("%*s\n", result[i].length, result[i].ptr); 1.314 } 1.315 1.316 @@ -762,32 +757,30 @@ 1.317 You should declare test cases and subroutines in a header file per test unit 1.318 and implement them as you would implement normal functions. 1.319 ```C 1.320 - /* myunit.h */ 1.321 + // myunit.h 1.322 UCX_TEST(function_name); 1.323 - UCX_TEST_SUBROUTINE(subroutine_name, paramlist); /* optional */ 1.324 + UCX_TEST_SUBROUTINE(subroutine_name, paramlist); // optional 1.325 1.326 1.327 - /* myunit.c */ 1.328 + // myunit.c 1.329 UCX_TEST_SUBROUTINE(subroutine_name, paramlist) { 1.330 - /* ... reusable tests with UCX_TEST_ASSERT() ... */ 1.331 + // ... reusable tests with UCX_TEST_ASSERT() ... 1.332 } 1.333 1.334 UCX_TEST(function_name) { 1.335 - /* ... resource allocation and other test preparation ... */ 1.336 + // ... resource allocation and other test preparation ... 1.337 1.338 - /* mandatory marker for the start of the tests */ 1.339 + // mandatory marker for the start of the tests 1.340 UCX_TEST_BEGIN 1.341 1.342 - /* ... verifications with UCX_TEST_ASSERT() ... 1.343 - * (and/or calls with UCX_TEST_CALL_SUBROUTINE()) 1.344 - */ 1.345 + // ... verifications with UCX_TEST_ASSERT() ... 1.346 + // (and/or calls with UCX_TEST_CALL_SUBROUTINE()) 1.347 1.348 - /* mandatory marker for the end of the tests */ 1.349 + // mandatory marker for the end of the tests 1.350 UCX_TEST_END 1.351 1.352 - /* ... resource cleanup ... 1.353 - * (all code after UCX_TEST_END is always executed) 1.354 - */ 1.355 + // ... resource cleanup ... 1.356 + // (all code after UCX_TEST_END is always executed) 1.357 } 1.358 ``` 1.359 If you want to use the `UCX_TEST_ASSERT()` macro in a function, you are 1.360 @@ -800,8 +793,8 @@ 1.361 UcxTestSuite* suite = ucx_test_suite_new(); 1.362 ucx_test_register(suite, testMyTestCase01); 1.363 ucx_test_register(suite, testMyTestCase02); 1.364 - /* ... */ 1.365 - ucx_test_run(suite, stdout); /* stdout, or any other FILE stream */ 1.366 + // ... 1.367 + ucx_test_run(suite, stdout); // stdout, or any other FILE stream 1.368 ``` 1.369 1.370 ## Utilities 1.371 @@ -831,7 +824,7 @@ 1.372 return 1; 1.373 } 1.374 1.375 - FILE *srcf = fopen(argv[1], "r"); /* insert error handling on your own */ 1.376 + FILE *srcf = fopen(argv[1], "r"); // insert error handling on your own 1.377 FILE *destf = fopen(argv[2], "w"); 1.378 1.379 size_t n = ucx_stream_copy(srcf, destf, fread, fwrite); 1.380 @@ -866,7 +859,7 @@ 1.381 i, prime(i) ? "prime" : "not prime"); 1.382 } 1.383 1.384 -/* print the result to stdout */ 1.385 +// print the result to stdout 1.386 printf("%s", (char*)strbuffer->space); 1.387 1.388 ucx_buffer_free(strbuffer);