| 120 * Not used as a status and never returned by any function. |
119 * Not used as a status and never returned by any function. |
| 121 * |
120 * |
| 122 * You can use this enumerator to check for all "good" status results |
121 * You can use this enumerator to check for all "good" status results |
| 123 * by checking if the status is less than @c CX_PROPERTIES_OK. |
122 * by checking if the status is less than @c CX_PROPERTIES_OK. |
| 124 * |
123 * |
| 125 * A "good" status means, that you can refill data and continue parsing. |
124 * A "good" status means that you can refill data and continue parsing. |
| 126 */ |
125 */ |
| 127 CX_PROPERTIES_OK, |
126 CX_PROPERTIES_OK, |
| 128 /** |
127 /** |
| 129 * Input buffer is @c NULL. |
128 * Input buffer is @c NULL. |
| 130 */ |
129 */ |
| 131 CX_PROPERTIES_NULL_INPUT, |
130 CX_PROPERTIES_NULL_INPUT, |
| 132 /** |
131 /** |
| 133 * The line contains a delimiter, but no key. |
132 * The line contains a delimiter but no key. |
| 134 */ |
133 */ |
| 135 CX_PROPERTIES_INVALID_EMPTY_KEY, |
134 CX_PROPERTIES_INVALID_EMPTY_KEY, |
| 136 /** |
135 /** |
| 137 * The line contains data, but no delimiter. |
136 * The line contains data but no delimiter. |
| 138 */ |
137 */ |
| 139 CX_PROPERTIES_INVALID_MISSING_DELIMITER, |
138 CX_PROPERTIES_INVALID_MISSING_DELIMITER, |
| 140 /** |
139 /** |
| 141 * More internal buffer was needed, but could not be allocated. |
140 * More internal buffer was needed, but could not be allocated. |
| 142 */ |
141 */ |
| 198 typedef struct cx_properties_sink_s CxPropertiesSink; |
197 typedef struct cx_properties_sink_s CxPropertiesSink; |
| 199 |
198 |
| 200 /** |
199 /** |
| 201 * A function that consumes a k/v-pair in a sink. |
200 * A function that consumes a k/v-pair in a sink. |
| 202 * |
201 * |
| 203 * The sink could be e.g. a map and the sink function would be calling |
202 * The sink could be a map, and the sink function would be calling |
| 204 * a map function to store the k/v-pair. |
203 * a map function to store the k/v-pair. |
| 205 * |
204 * |
| 206 * @param prop the properties interface that wants to sink a k/v-pair |
205 * @param prop the properties interface that wants to sink a k/v-pair |
| 207 * @param sink the sink |
206 * @param sink the sink |
| 208 * @param key the key |
207 * @param key the key |
| 209 * @param value the value |
208 * @param value the value |
| 210 * @retval zero success |
209 * @retval zero success |
| 211 * @retval non-zero sinking the k/v-pair failed |
210 * @retval non-zero sinking the k/v-pair failed |
| 212 */ |
211 */ |
| 213 cx_attr_nonnull |
|
| 214 typedef int(*cx_properties_sink_func)( |
212 typedef int(*cx_properties_sink_func)( |
| 215 CxProperties *prop, |
213 CxProperties *prop, |
| 216 CxPropertiesSink *sink, |
214 CxPropertiesSink *sink, |
| 217 cxstring key, |
215 cxstring key, |
| 218 cxstring value |
216 cxstring value |
| 255 * @param src the source |
253 * @param src the source |
| 256 * @param target a string buffer where the read data shall be stored |
254 * @param target a string buffer where the read data shall be stored |
| 257 * @retval zero success |
255 * @retval zero success |
| 258 * @retval non-zero reading the data failed |
256 * @retval non-zero reading the data failed |
| 259 */ |
257 */ |
| 260 cx_attr_nonnull |
|
| 261 typedef int(*cx_properties_read_func)( |
258 typedef int(*cx_properties_read_func)( |
| 262 CxProperties *prop, |
259 CxProperties *prop, |
| 263 CxPropertiesSource *src, |
260 CxPropertiesSource *src, |
| 264 cxstring *target |
261 cxstring *target |
| 265 ); |
262 ); |
| 270 * @param prop the properties interface that wants to read from the source |
267 * @param prop the properties interface that wants to read from the source |
| 271 * @param src the source |
268 * @param src the source |
| 272 * @retval zero initialization was successful |
269 * @retval zero initialization was successful |
| 273 * @retval non-zero otherwise |
270 * @retval non-zero otherwise |
| 274 */ |
271 */ |
| 275 cx_attr_nonnull |
|
| 276 typedef int(*cx_properties_read_init_func)( |
272 typedef int(*cx_properties_read_init_func)( |
| 277 CxProperties *prop, |
273 CxProperties *prop, |
| 278 CxPropertiesSource *src |
274 CxPropertiesSource *src |
| 279 ); |
275 ); |
| 280 |
276 |
| 329 * @param prop the properties interface |
324 * @param prop the properties interface |
| 330 * @param config the properties configuration |
325 * @param config the properties configuration |
| 331 * @see cxPropertiesInitDefault() |
326 * @see cxPropertiesInitDefault() |
| 332 */ |
327 */ |
| 333 cx_attr_nonnull |
328 cx_attr_nonnull |
| 334 cx_attr_export |
329 CX_EXPORT void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); |
| 335 void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); |
|
| 336 |
330 |
| 337 /** |
331 /** |
| 338 * Destroys the properties interface. |
332 * Destroys the properties interface. |
| 339 * |
333 * |
| 340 * @note Even when you are certain that you did not use the interface in a |
334 * @note Even when you are certain that you did not use the interface in a |
| 341 * way that caused a memory allocation, you should call this function anyway. |
335 * way that caused a memory allocation, you should call this function anyway. |
| 342 * Future versions of the library might add features that need additional memory |
336 * Future versions of the library might add features that need additional memory, |
| 343 * and you really don't want to search the entire code where you might need |
337 * and you really don't want to search the entire code where you might need to |
| 344 * add call to this function. |
338 * add a call to this function. |
| 345 * |
339 * |
| 346 * @param prop the properties interface |
340 * @param prop the properties interface |
| 347 */ |
341 */ |
| 348 cx_attr_nonnull |
342 cx_attr_nonnull |
| 349 cx_attr_export |
343 CX_EXPORT void cxPropertiesDestroy(CxProperties *prop); |
| 350 void cxPropertiesDestroy(CxProperties *prop); |
|
| 351 |
344 |
| 352 /** |
345 /** |
| 353 * Destroys and re-initializes the properties interface. |
346 * Destroys and re-initializes the properties interface. |
| 354 * |
347 * |
| 355 * You might want to use this, to reset the parser after |
348 * You might want to use this to reset the parser after |
| 356 * encountering a syntax error. |
349 * encountering a syntax error. |
| 357 * |
350 * |
| 358 * @param prop the properties interface |
351 * @param prop the properties interface |
| 359 */ |
352 */ |
| 360 cx_attr_nonnull |
353 cx_attr_nonnull |
| 361 static inline void cxPropertiesReset(CxProperties *prop) { |
354 CX_EXPORT void cxPropertiesReset(CxProperties *prop); |
| 362 CxPropertiesConfig config = prop->config; |
|
| 363 cxPropertiesDestroy(prop); |
|
| 364 cxPropertiesInit(prop, config); |
|
| 365 } |
|
| 366 |
355 |
| 367 /** |
356 /** |
| 368 * Initialize a properties parser with the default configuration. |
357 * Initialize a properties parser with the default configuration. |
| 369 * |
358 * |
| 370 * @param prop (@c CxProperties*) the properties interface |
359 * @param prop (@c CxProperties*) the properties interface |
| 371 * @see cxPropertiesInit() |
360 * @see cxPropertiesInit() |
| 372 */ |
361 */ |
| 373 #define cxPropertiesInitDefault(prop) \ |
362 #define cxPropertiesInitDefault(prop) \ |
| 374 cxPropertiesInit(prop, cx_properties_config_default) |
363 cxPropertiesInit(prop, cx_properties_config_default) |
| 375 |
364 |
| 376 /** |
365 /** |
| 377 * Fills the input buffer with data. |
366 * Fills the input buffer with data. |
| 378 * |
367 * |
| 379 * After calling this function, you can parse the data by calling |
368 * After calling this function, you can parse the data by calling |
| 392 * @param len the length of the data |
381 * @param len the length of the data |
| 393 * @retval zero success |
382 * @retval zero success |
| 394 * @retval non-zero a memory allocation was necessary but failed |
383 * @retval non-zero a memory allocation was necessary but failed |
| 395 * @see cxPropertiesFill() |
384 * @see cxPropertiesFill() |
| 396 */ |
385 */ |
| |
386 cx_attr_nonnull cx_attr_access_r(2, 3) |
| |
387 CX_EXPORT int cxPropertiesFilln(CxProperties *prop, const char *buf, size_t len); |
| |
388 |
| |
389 /** |
| |
390 * Internal function, do not use. |
| |
391 * |
| |
392 * @param prop the properties interface |
| |
393 * @param str the text to fill in |
| |
394 * @retval zero success |
| |
395 * @retval non-zero a memory allocation was necessary but failed |
| |
396 */ |
| 397 cx_attr_nonnull |
397 cx_attr_nonnull |
| 398 cx_attr_access_r(2, 3) |
398 CX_INLINE int cx_properties_fill(CxProperties *prop, cxstring str) { |
| 399 cx_attr_export |
|
| 400 int cxPropertiesFilln( |
|
| 401 CxProperties *prop, |
|
| 402 const char *buf, |
|
| 403 size_t len |
|
| 404 ); |
|
| 405 |
|
| 406 #ifdef __cplusplus |
|
| 407 } // extern "C" |
|
| 408 cx_attr_nonnull |
|
| 409 static inline int cxPropertiesFill( |
|
| 410 CxProperties *prop, |
|
| 411 cxstring str |
|
| 412 ) { |
|
| 413 return cxPropertiesFilln(prop, str.ptr, str.length); |
399 return cxPropertiesFilln(prop, str.ptr, str.length); |
| 414 } |
400 } |
| 415 |
401 |
| 416 cx_attr_nonnull |
|
| 417 static inline int cxPropertiesFill( |
|
| 418 CxProperties *prop, |
|
| 419 cxmutstr str |
|
| 420 ) { |
|
| 421 return cxPropertiesFilln(prop, str.ptr, str.length); |
|
| 422 } |
|
| 423 |
|
| 424 cx_attr_nonnull |
|
| 425 cx_attr_cstr_arg(2) |
|
| 426 static inline int cxPropertiesFill( |
|
| 427 CxProperties *prop, |
|
| 428 const char *str |
|
| 429 ) { |
|
| 430 return cxPropertiesFilln(prop, str, strlen(str)); |
|
| 431 } |
|
| 432 |
|
| 433 extern "C" { |
|
| 434 #else // __cplusplus |
|
| 435 /** |
402 /** |
| 436 * Fills the input buffer with data. |
403 * Fills the input buffer with data. |
| 437 * |
404 * |
| 438 * After calling this function, you can parse the data by calling |
405 * After calling this function, you can parse the data by calling |
| 439 * cxPropertiesNext(). |
406 * cxPropertiesNext(). |
| 450 * @param str the text to fill in |
417 * @param str the text to fill in |
| 451 * @retval zero success |
418 * @retval zero success |
| 452 * @retval non-zero a memory allocation was necessary but failed |
419 * @retval non-zero a memory allocation was necessary but failed |
| 453 * @see cxPropertiesFilln() |
420 * @see cxPropertiesFilln() |
| 454 */ |
421 */ |
| 455 #define cxPropertiesFill(prop, str) _Generic((str), \ |
422 #define cxPropertiesFill(prop, str) cx_properties_fill(prop, cx_strcast(str)) |
| 456 cxstring: cx_properties_fill_cxstr, \ |
423 |
| 457 cxmutstr: cx_properties_fill_mutstr, \ |
424 /** |
| 458 char*: cx_properties_fill_str, \ |
425 * Specifies stack memory that shall be used as an internal buffer. |
| 459 const char*: cx_properties_fill_str) \ |
|
| 460 (prop, str) |
|
| 461 |
|
| 462 /** |
|
| 463 * @copydoc cxPropertiesFill() |
|
| 464 */ |
|
| 465 cx_attr_nonnull |
|
| 466 static inline int cx_properties_fill_cxstr( |
|
| 467 CxProperties *prop, |
|
| 468 cxstring str |
|
| 469 ) { |
|
| 470 return cxPropertiesFilln(prop, str.ptr, str.length); |
|
| 471 } |
|
| 472 |
|
| 473 /** |
|
| 474 * @copydoc cxPropertiesFill() |
|
| 475 */ |
|
| 476 cx_attr_nonnull |
|
| 477 static inline int cx_properties_fill_mutstr( |
|
| 478 CxProperties *prop, |
|
| 479 cxmutstr str |
|
| 480 ) { |
|
| 481 return cxPropertiesFilln(prop, str.ptr, str.length); |
|
| 482 } |
|
| 483 |
|
| 484 /** |
|
| 485 * @copydoc cxPropertiesFill() |
|
| 486 */ |
|
| 487 cx_attr_nonnull |
|
| 488 cx_attr_cstr_arg(2) |
|
| 489 static inline int cx_properties_fill_str( |
|
| 490 CxProperties *prop, |
|
| 491 const char *str |
|
| 492 ) { |
|
| 493 return cxPropertiesFilln(prop, str, strlen(str)); |
|
| 494 } |
|
| 495 #endif |
|
| 496 |
|
| 497 /** |
|
| 498 * Specifies stack memory that shall be used as internal buffer. |
|
| 499 * |
426 * |
| 500 * @param prop the properties interface |
427 * @param prop the properties interface |
| 501 * @param buf a pointer to stack memory |
428 * @param buf a pointer to stack memory |
| 502 * @param capacity the capacity of the stack memory |
429 * @param capacity the capacity of the stack memory |
| 503 */ |
430 */ |
| 504 cx_attr_nonnull |
431 cx_attr_nonnull |
| 505 cx_attr_export |
432 CX_EXPORT void cxPropertiesUseStack(CxProperties *prop, char *buf, size_t capacity); |
| 506 void cxPropertiesUseStack( |
|
| 507 CxProperties *prop, |
|
| 508 char *buf, |
|
| 509 size_t capacity |
|
| 510 ); |
|
| 511 |
433 |
| 512 /** |
434 /** |
| 513 * Retrieves the next key/value-pair. |
435 * Retrieves the next key/value-pair. |
| 514 * |
436 * |
| 515 * This function returns zero as long as there are key/value-pairs found. |
437 * This function returns zero as long as there are key/value-pairs found. |
| 537 * @retval CX_PROPERTIES_NULL_INPUT the input buffer was never filled |
459 * @retval CX_PROPERTIES_NULL_INPUT the input buffer was never filled |
| 538 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
460 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
| 539 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
461 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
| 540 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
462 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
| 541 */ |
463 */ |
| 542 cx_attr_nonnull |
464 cx_attr_nonnull cx_attr_nodiscard |
| 543 cx_attr_nodiscard |
465 CX_EXPORT CxPropertiesStatus cxPropertiesNext(CxProperties *prop, cxstring *key, cxstring *value); |
| 544 cx_attr_export |
|
| 545 CxPropertiesStatus cxPropertiesNext( |
|
| 546 CxProperties *prop, |
|
| 547 cxstring *key, |
|
| 548 cxstring *value |
|
| 549 ); |
|
| 550 |
466 |
| 551 /** |
467 /** |
| 552 * Creates a properties sink for an UCX map. |
468 * Creates a properties sink for an UCX map. |
| 553 * |
469 * |
| 554 * The values stored in the map will be pointers to freshly allocated, |
470 * The values stored in the map will be pointers to freshly allocated, |
| 560 * |
476 * |
| 561 * @param map the map that shall consume the k/v-pairs. |
477 * @param map the map that shall consume the k/v-pairs. |
| 562 * @return the sink |
478 * @return the sink |
| 563 * @see cxPropertiesLoad() |
479 * @see cxPropertiesLoad() |
| 564 */ |
480 */ |
| 565 cx_attr_nonnull |
481 cx_attr_nonnull cx_attr_nodiscard |
| 566 cx_attr_nodiscard |
482 CX_EXPORT CxPropertiesSink cxPropertiesMapSink(CxMap *map); |
| 567 cx_attr_export |
|
| 568 CxPropertiesSink cxPropertiesMapSink(CxMap *map); |
|
| 569 |
483 |
| 570 /** |
484 /** |
| 571 * Creates a properties source based on an UCX string. |
485 * Creates a properties source based on an UCX string. |
| 572 * |
486 * |
| 573 * @param str the string |
487 * @param str the string |
| 574 * @return the properties source |
488 * @return the properties source |
| 575 * @see cxPropertiesLoad() |
489 * @see cxPropertiesLoad() |
| 576 */ |
490 */ |
| 577 cx_attr_nodiscard |
491 cx_attr_nodiscard |
| 578 cx_attr_export |
492 CX_EXPORT CxPropertiesSource cxPropertiesStringSource(cxstring str); |
| 579 CxPropertiesSource cxPropertiesStringSource(cxstring str); |
|
| 580 |
493 |
| 581 /** |
494 /** |
| 582 * Creates a properties source based on C string with the specified length. |
495 * Creates a properties source based on C string with the specified length. |
| 583 * |
496 * |
| 584 * @param str the string |
497 * @param str the string |
| 585 * @param len the length |
498 * @param len the length |
| 586 * @return the properties source |
499 * @return the properties source |
| 587 * @see cxPropertiesLoad() |
500 * @see cxPropertiesLoad() |
| 588 */ |
501 */ |
| 589 cx_attr_nonnull |
502 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1, 2) |
| 590 cx_attr_nodiscard |
503 CX_EXPORT CxPropertiesSource cxPropertiesCstrnSource(const char *str, size_t len); |
| 591 cx_attr_access_r(1, 2) |
|
| 592 cx_attr_export |
|
| 593 CxPropertiesSource cxPropertiesCstrnSource(const char *str, size_t len); |
|
| 594 |
504 |
| 595 /** |
505 /** |
| 596 * Creates a properties source based on a C string. |
506 * Creates a properties source based on a C string. |
| 597 * |
507 * |
| 598 * The length will be determined with strlen(), so the string MUST be |
508 * The length will be determined with strlen(), so the string MUST be |
| 600 * |
510 * |
| 601 * @param str the string |
511 * @param str the string |
| 602 * @return the properties source |
512 * @return the properties source |
| 603 * @see cxPropertiesLoad() |
513 * @see cxPropertiesLoad() |
| 604 */ |
514 */ |
| 605 cx_attr_nonnull |
515 cx_attr_nonnull cx_attr_nodiscard cx_attr_cstr_arg(1) |
| 606 cx_attr_nodiscard |
516 CX_EXPORT CxPropertiesSource cxPropertiesCstrSource(const char *str); |
| 607 cx_attr_cstr_arg(1) |
|
| 608 cx_attr_export |
|
| 609 CxPropertiesSource cxPropertiesCstrSource(const char *str); |
|
| 610 |
517 |
| 611 /** |
518 /** |
| 612 * Creates a properties source based on an FILE. |
519 * Creates a properties source based on an FILE. |
| 613 * |
520 * |
| 614 * @param file the file |
521 * @param file the file |
| 615 * @param chunk_size how many bytes may be read in one operation |
522 * @param chunk_size how many bytes may be read in one operation |
| 616 * |
523 * |
| 617 * @return the properties source |
524 * @return the properties source |
| 618 * @see cxPropertiesLoad() |
525 * @see cxPropertiesLoad() |
| 619 */ |
526 */ |
| 620 cx_attr_nonnull |
527 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1) |
| 621 cx_attr_nodiscard |
528 CX_EXPORT CxPropertiesSource cxPropertiesFileSource(FILE *file, size_t chunk_size); |
| 622 cx_attr_access_r(1) |
|
| 623 cx_attr_export |
|
| 624 CxPropertiesSource cxPropertiesFileSource(FILE *file, size_t chunk_size); |
|
| 625 |
529 |
| 626 |
530 |
| 627 /** |
531 /** |
| 628 * Loads properties data from a source and transfers it to a sink. |
532 * Loads properties data from a source and transfers it to a sink. |
| 629 * |
533 * |
| 651 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
555 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
| 652 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
556 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
| 653 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
557 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
| 654 */ |
558 */ |
| 655 cx_attr_nonnull |
559 cx_attr_nonnull |
| 656 cx_attr_export |
560 CX_EXPORT CxPropertiesStatus cxPropertiesLoad(CxProperties *prop, |
| 657 CxPropertiesStatus cxPropertiesLoad( |
561 CxPropertiesSink sink, CxPropertiesSource source); |
| 658 CxProperties *prop, |
|
| 659 CxPropertiesSink sink, |
|
| 660 CxPropertiesSource source |
|
| 661 ); |
|
| 662 |
562 |
| 663 #ifdef __cplusplus |
563 #ifdef __cplusplus |
| 664 } // extern "C" |
564 } // extern "C" |
| 665 #endif |
565 #endif |
| 666 |
566 |