60 /* --------------------- |
60 /* --------------------- |
61 * Somewhere in a header |
61 * Somewhere in a header |
62 */ |
62 */ |
63 typedef struct { |
63 typedef struct { |
64 time_t ts; |
64 time_t ts; |
65 // other important data |
65 /* other important data */ |
66 } MyObject; |
66 } MyObject; |
67 |
67 |
68 /* ----------- |
68 /* ----------- |
69 * Source code |
69 * Source code |
70 */ |
70 */ |
71 |
71 |
72 UcxAVLTree* tree = ucx_avl_new(ucx_longintcmp); |
72 UcxAVLTree* tree = ucx_avl_new(ucx_longintcmp); |
73 // ... populate tree with objects, use '& MyObject.ts' as key ... |
73 /* ... populate tree with objects, use '& MyObject.ts' as key ... */ |
74 |
74 |
75 |
75 |
76 // Now find every item, with 30 <= ts <= 70 |
76 /* Now find every item, with 30 <= ts <= 70 */ |
77 time_t ts_start = 30; |
77 time_t ts_start = 30; |
78 time_t ts_end = 70; |
78 time_t ts_end = 70; |
79 |
79 |
80 printf("Values in range:\n"); |
80 printf("Values in range:\n"); |
81 for ( |
81 for ( |
139 |
139 |
140 const size_t chunksize = 256; |
140 const size_t chunksize = 256; |
141 |
141 |
142 UcxBuffer* linebuf = |
142 UcxBuffer* linebuf = |
143 ucx_buffer_new( |
143 ucx_buffer_new( |
144 NULL, // the buffer should manage the memory area for us |
144 NULL, /* the buffer should manage the memory area for us */ |
145 chunksize, // initial buffer size should be the chunk size |
145 2*chunksize, /* initial size should be twice the chunk size */ |
146 UCX_BUFFER_AUTOEXTEND); // the buffer will grow when necessary |
146 UCX_BUFFER_AUTOEXTEND); /* the buffer will grow when necessary */ |
147 |
147 |
148 size_t lineno = 1; |
148 size_t lineno = 1; |
149 do { |
149 do { |
150 // read line chunk |
150 /* read line chunk */ |
151 size_t read = ucx_stream_ncopy( |
151 size_t read = ucx_stream_ncopy( |
152 input, linebuf, fread, ucx_buffer_write, chunksize); |
152 input, linebuf, fread, ucx_buffer_write, chunksize); |
153 if (read == 0) break; |
153 if (read == 0) break; |
154 |
154 |
155 // handle line endings |
155 /* handle line endings */ |
156 do { |
156 do { |
157 sstr_t bufstr = ucx_buffer_to_sstr(linebuf); |
157 sstr_t bufstr = ucx_buffer_to_sstr(linebuf); |
158 sstr_t nl = sstrchr(bufstr, '\n'); |
158 sstr_t nl = sstrchr(bufstr, '\n'); |
159 if (nl.length == 0) break; |
159 if (nl.length == 0) break; |
160 |
160 |
161 size_t linelen = bufstr.length - nl.length; |
161 size_t linelen = bufstr.length - nl.length; |
162 sstr_t linestr = sstrsubsl(bufstr, 0, linelen); |
162 sstr_t linestr = sstrsubsl(bufstr, 0, linelen); |
163 |
163 |
164 printf("%zu: %" PRIsstr "\n", lineno++, SFMT(linestr)); |
164 printf("%zu: %" PRIsstr "\n", lineno++, SFMT(linestr)); |
165 |
165 |
166 // shift the buffer to the next line |
166 /* shift the buffer to the next line */ |
167 ucx_buffer_shift_left(linebuf, linelen+1); |
167 ucx_buffer_shift_left(linebuf, linelen+1); |
168 } while(1); |
168 } while(1); |
169 |
169 |
170 } while(1); |
170 } while(1); |
171 |
171 |
172 // print the 'noeol' line, if any |
172 /* print the 'noeol' line, if any */ |
173 sstr_t lastline = ucx_buffer_to_sstr(linebuf); |
173 sstr_t lastline = ucx_buffer_to_sstr(linebuf); |
174 if (lastline.length > 0) { |
174 if (lastline.length > 0) { |
175 printf("%zu: %" PRIsstr, lineno, SFMT(lastline)); |
175 printf("%zu: %" PRIsstr, lineno, SFMT(lastline)); |
176 } |
176 } |
177 |
177 |
188 *Required modules:* [Allocator](#allocator) |
188 *Required modules:* [Allocator](#allocator) |
189 |
189 |
190 This module provides the data structure and several functions for a doubly |
190 This module provides the data structure and several functions for a doubly |
191 linked list. Among the common operations like insert, remove, search and sort, |
191 linked list. Among the common operations like insert, remove, search and sort, |
192 we allow convenient iteration via a special `UCX_FOREACH` macro. |
192 we allow convenient iteration via a special `UCX_FOREACH` macro. |
|
193 |
|
194 ### Remove duplicates from an array of strings |
|
195 |
|
196 Assume you are given an array of `sstr_t` and want to create a list of these |
|
197 strings without duplicates. |
|
198 ```C |
|
199 #include <stdio.h> |
|
200 #include <ucx/list.h> |
|
201 #include <ucx/string.h> |
|
202 #include <ucx/utils.h> |
|
203 |
|
204 UcxList* remove_duplicates(sstr_t* array, size_t arrlen) { |
|
205 UcxList* list = NULL; |
|
206 for (size_t i = 0 ; i < arrlen ; ++i) { |
|
207 if (ucx_list_find(list, array+i, ucx_sstrcmp, NULL) == -1) { |
|
208 sstr_t* s = malloc(sizeof(sstr_t)); |
|
209 *s = sstrdup(array[i]); |
|
210 list = ucx_list_append(list, s); |
|
211 } |
|
212 } |
|
213 return list; |
|
214 } |
|
215 |
|
216 /* we will need this function to clean up the list contents later */ |
|
217 void free_sstr(void* ptr) { |
|
218 sstr_t* s = ptr; |
|
219 free(s->ptr); |
|
220 free(s); |
|
221 } |
|
222 |
|
223 /* ... */ |
|
224 |
|
225 sstr_t* array = /* some array of strings */ |
|
226 size_t arrlen = /* the length of the array */ |
|
227 |
|
228 UcxList* list = remove_duplicates(array,arrlen); |
|
229 |
|
230 /* Iterate over the list and print the elements */ |
|
231 UCX_FOREACH(elem, list) { |
|
232 sstr_t s = *((sstr_t*)elem->data); |
|
233 printf("%" PRIsstr "\n", SFMT(s)); |
|
234 } |
|
235 |
|
236 /* Use our free function to free the duplicated strings. */ |
|
237 ucx_list_free_content(list, free_sstr); |
|
238 ucx_list_free(list); |
|
239 ``` |
193 |
240 |
194 ## Logging |
241 ## Logging |
195 |
242 |
196 *Header file:* [logging.h](api/logging_8h.html) |
243 *Header file:* [logging.h](api/logging_8h.html) |
197 *Required modules:* [Map](#map), [String](#string) |
244 *Required modules:* [Map](#map), [String](#string) |
231 The key/value pairs are stored within an UCX Map. |
278 The key/value pairs are stored within an UCX Map. |
232 |
279 |
233 ### Example: Loading properties from a file |
280 ### Example: Loading properties from a file |
234 |
281 |
235 ```C |
282 ```C |
236 // Open the file as usual |
283 /* Open the file as usual */ |
237 FILE* file = fopen("myprops.properties", "r"); |
284 FILE* file = fopen("myprops.properties", "r"); |
238 if (!file) { |
285 if (!file) { |
239 // error handling |
286 // error handling |
240 return 1; |
287 return 1; |
241 } |
288 } |
242 |
289 |
243 // Load the properties from the file |
290 /* Load the properties from the file */ |
244 UcxMap* myprops = ucx_map_new(16); |
291 UcxMap* myprops = ucx_map_new(16); |
245 if (ucx_properties_load(myprops, file)) { |
292 if (ucx_properties_load(myprops, file)) { |
246 // error handling |
293 /* ... error handling ... */ |
247 fclose(file); |
294 fclose(file); |
248 ucx_map_free(myprops); |
295 ucx_map_free(myprops); |
249 return 1; |
296 return 1; |
250 } |
297 } |
251 |
298 |
252 // Print out the key/value pairs |
299 /* Print out the key/value pairs */ |
253 char* propval; |
300 char* propval; |
254 UcxMapIterator propiter = ucx_map_iterator(myprops); |
301 UcxMapIterator propiter = ucx_map_iterator(myprops); |
255 UCX_MAP_FOREACH(key, propval, propiter) { |
302 UCX_MAP_FOREACH(key, propval, propiter) { |
256 printf("%s = %s\n", (char*)key.data, propval); |
303 printf("%s = %s\n", (char*)key.data, propval); |
257 } |
304 } |
258 |
305 |
259 // Don't forget to free the values before freeing the map |
306 /* Don't forget to free the values before freeing the map */ |
260 ucx_map_free_content(myprops, NULL); |
307 ucx_map_free_content(myprops, NULL); |
261 ucx_map_free(myprops); |
308 ucx_map_free(myprops); |
262 fclose(file); |
309 fclose(file); |
263 ``` |
310 ``` |
264 ## Stack |
311 ## Stack |
393 if (argc != 3) { |
440 if (argc != 3) { |
394 fprintf(stderr, "Use %s <src> <dest>", argv[0]); |
441 fprintf(stderr, "Use %s <src> <dest>", argv[0]); |
395 return 1; |
442 return 1; |
396 } |
443 } |
397 |
444 |
398 FILE *srcf = fopen(argv[1], "r"); // insert error handling on your own |
445 FILE *srcf = fopen(argv[1], "r"); /* insert error handling on your own */ |
399 FILE *destf = fopen(argv[2], "w"); |
446 FILE *destf = fopen(argv[2], "w"); |
400 |
447 |
401 size_t n = ucx_stream_copy(srcf, destf, fread, fwrite); |
448 size_t n = ucx_stream_copy(srcf, destf, fread, fwrite); |
402 printf("%zu bytes copied.\n", n); |
449 printf("%zu bytes copied.\n", n); |
403 |
450 |
428 for (unsigned int i = 2 ; i < 100 ; i++) { |
475 for (unsigned int i = 2 ; i < 100 ; i++) { |
429 ucx_bprintf(strbuffer, "Integer %d is %s\n", |
476 ucx_bprintf(strbuffer, "Integer %d is %s\n", |
430 i, prime(i) ? "prime" : "not prime"); |
477 i, prime(i) ? "prime" : "not prime"); |
431 } |
478 } |
432 |
479 |
433 // print the result to stdout |
480 /* print the result to stdout */ |
434 printf("%s", (char*)strbuffer->space); |
481 printf("%s", (char*)strbuffer->space); |
435 |
482 |
436 ucx_buffer_free(strbuffer); |
483 ucx_buffer_free(strbuffer); |
437 ``` |
484 ``` |