| 187 |
177 |
| 188 /** |
178 /** |
| 189 * Typedef for the properties interface. |
179 * Typedef for the properties interface. |
| 190 */ |
180 */ |
| 191 typedef struct cx_properties_s CxProperties; |
181 typedef struct cx_properties_s CxProperties; |
| 192 |
|
| 193 |
|
| 194 /** |
|
| 195 * Typedef for a properties sink. |
|
| 196 */ |
|
| 197 typedef struct cx_properties_sink_s CxPropertiesSink; |
|
| 198 |
|
| 199 /** |
|
| 200 * A function that consumes a k/v-pair in a sink. |
|
| 201 * |
|
| 202 * The sink could be a map, and the sink function would be calling |
|
| 203 * a map function to store the k/v-pair. |
|
| 204 * |
|
| 205 * @param prop the properties interface that wants to sink a k/v-pair |
|
| 206 * @param sink the sink |
|
| 207 * @param key the key |
|
| 208 * @param value the value |
|
| 209 * @retval zero success |
|
| 210 * @retval non-zero sinking the k/v-pair failed |
|
| 211 */ |
|
| 212 typedef int(*cx_properties_sink_func)( |
|
| 213 CxProperties *prop, |
|
| 214 CxPropertiesSink *sink, |
|
| 215 cxstring key, |
|
| 216 cxstring value |
|
| 217 ); |
|
| 218 |
|
| 219 /** |
|
| 220 * Defines a sink for k/v-pairs. |
|
| 221 */ |
|
| 222 struct cx_properties_sink_s { |
|
| 223 /** |
|
| 224 * The sink object. |
|
| 225 */ |
|
| 226 void *sink; |
|
| 227 /** |
|
| 228 * Optional custom data. |
|
| 229 */ |
|
| 230 void *data; |
|
| 231 /** |
|
| 232 * A function for consuming k/v-pairs into the sink. |
|
| 233 */ |
|
| 234 cx_properties_sink_func sink_func; |
|
| 235 }; |
|
| 236 |
|
| 237 |
|
| 238 /** |
|
| 239 * Typedef for a properties source. |
|
| 240 */ |
|
| 241 typedef struct cx_properties_source_s CxPropertiesSource; |
|
| 242 |
|
| 243 /** |
|
| 244 * A function that reads data from a source. |
|
| 245 * |
|
| 246 * When the source is depleted, implementations SHALL provide an empty |
|
| 247 * string in the @p target and return zero. |
|
| 248 * A non-zero return value is only permitted in case of an error. |
|
| 249 * |
|
| 250 * The meaning of the optional parameters is implementation-dependent. |
|
| 251 * |
|
| 252 * @param prop the properties interface that wants to read from the source |
|
| 253 * @param src the source |
|
| 254 * @param target a string buffer where the read data shall be stored |
|
| 255 * @retval zero success |
|
| 256 * @retval non-zero reading the data failed |
|
| 257 */ |
|
| 258 typedef int(*cx_properties_read_func)( |
|
| 259 CxProperties *prop, |
|
| 260 CxPropertiesSource *src, |
|
| 261 cxstring *target |
|
| 262 ); |
|
| 263 |
|
| 264 /** |
|
| 265 * A function that may initialize additional memory for the source. |
|
| 266 * |
|
| 267 * @param prop the properties interface that wants to read from the source |
|
| 268 * @param src the source |
|
| 269 * @retval zero initialization was successful |
|
| 270 * @retval non-zero otherwise |
|
| 271 */ |
|
| 272 typedef int(*cx_properties_read_init_func)( |
|
| 273 CxProperties *prop, |
|
| 274 CxPropertiesSource *src |
|
| 275 ); |
|
| 276 |
|
| 277 /** |
|
| 278 * A function that cleans memory initialized by the read_init_func. |
|
| 279 * |
|
| 280 * @param prop the properties interface that wants to read from the source |
|
| 281 * @param src the source |
|
| 282 */ |
|
| 283 typedef void(*cx_properties_read_clean_func)( |
|
| 284 CxProperties *prop, |
|
| 285 CxPropertiesSource *src |
|
| 286 ); |
|
| 287 |
|
| 288 /** |
|
| 289 * Defines a properties source. |
|
| 290 */ |
|
| 291 struct cx_properties_source_s { |
|
| 292 /** |
|
| 293 * The source object. |
|
| 294 * |
|
| 295 * For example, a file stream or a string. |
|
| 296 */ |
|
| 297 void *src; |
|
| 298 /** |
|
| 299 * Optional additional data pointer. |
|
| 300 */ |
|
| 301 void *data_ptr; |
|
| 302 /** |
|
| 303 * Optional size information. |
|
| 304 */ |
|
| 305 size_t data_size; |
|
| 306 /** |
|
| 307 * A function that reads data from the source. |
|
| 308 */ |
|
| 309 cx_properties_read_func read_func; |
|
| 310 /** |
|
| 311 * Optional function that may prepare the source for reading data. |
|
| 312 */ |
|
| 313 cx_properties_read_init_func read_init_func; |
|
| 314 /** |
|
| 315 * Optional function that cleans additional memory allocated by the |
|
| 316 * read_init_func. |
|
| 317 */ |
|
| 318 cx_properties_read_clean_func read_clean_func; |
|
| 319 }; |
|
| 320 |
182 |
| 321 /** |
183 /** |
| 322 * Initialize a properties interface. |
184 * Initialize a properties interface. |
| 323 * |
185 * |
| 324 * @param prop the properties interface |
186 * @param prop the properties interface |
| 463 */ |
325 */ |
| 464 cx_attr_nonnull cx_attr_nodiscard |
326 cx_attr_nonnull cx_attr_nodiscard |
| 465 CX_EXPORT CxPropertiesStatus cxPropertiesNext(CxProperties *prop, cxstring *key, cxstring *value); |
327 CX_EXPORT CxPropertiesStatus cxPropertiesNext(CxProperties *prop, cxstring *key, cxstring *value); |
| 466 |
328 |
| 467 /** |
329 /** |
| 468 * Creates a properties sink for an UCX map. |
330 * The size of the stack memory that `cxPropertiesLoad()` will reserve with `cxPropertiesUseStack()`. |
| 469 * |
331 */ |
| 470 * The values stored in the map will be pointers to freshly allocated, |
332 CX_EXPORT extern const unsigned cx_properties_load_buf_size; |
| 471 * zero-terminated C strings (@c char*), which means the @p map should have been |
333 |
| 472 * created with #CX_STORE_POINTERS. |
334 /** |
| 473 * |
335 * The size of the stack memory that `cxPropertiesLoad()` will use to read contents from the file. |
| 474 * The cxDefaultAllocator will be used unless you specify a custom |
336 */ |
| 475 * allocator in the optional @c data field of the returned sink. |
337 CX_EXPORT extern const unsigned cx_properties_load_fill_size; |
| 476 * |
338 |
| 477 * @param map the map that shall consume the k/v-pairs. |
339 /** |
| 478 * @return the sink |
340 * Internal function - use cxPropertiesLoad() instead. |
| 479 * @see cxPropertiesLoad() |
341 * |
| 480 */ |
342 * @param config the parser config |
| 481 cx_attr_nonnull cx_attr_nodiscard |
343 * @param filename the file name |
| 482 CX_EXPORT CxPropertiesSink cxPropertiesMapSink(CxMap *map); |
344 * @param target the target map |
| 483 |
345 * @return status code |
| 484 /** |
346 */ |
| 485 * Creates a properties source based on an UCX string. |
347 cx_attr_nonnull |
| 486 * |
348 CX_EXPORT CxPropertiesStatus cx_properties_load(CxPropertiesConfig config, |
| 487 * @param str the string |
349 cxstring filename, CxMap *target); |
| 488 * @return the properties source |
350 |
| 489 * @see cxPropertiesLoad() |
351 /** |
| 490 */ |
352 * Loads properties from a file and inserts them into a map. |
| 491 cx_attr_nodiscard |
353 * |
| 492 CX_EXPORT CxPropertiesSource cxPropertiesStringSource(cxstring str); |
354 * Entries are added to the map, possibly overwriting existing entries. |
| 493 |
355 * |
| 494 /** |
356 * The map must either store pointers of type @c char*, or elements of type cxmutstr. |
| 495 * Creates a properties source based on C string with the specified length. |
357 * Any other configuration is not supported. |
| 496 * |
358 * |
| 497 * @param str the string |
359 * @param config the parser config |
| 498 * @param len the length |
360 * @param filename (any string) the absolute or relative path to the file |
| 499 * @return the properties source |
361 * @param target (@c CxMap*) the map where the properties shall be added |
| 500 * @see cxPropertiesLoad() |
362 * @retval CX_PROPERTIES_NO_ERROR (zero) at least one key/value pair was found |
| 501 */ |
363 * @retval CX_PROPERTIES_NO_DATA the file is syntactically OK, but does not contain properties |
| 502 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1, 2) |
364 * @retval CX_PROPERTIES_INCOMPLETE_DATA unexpected end of file |
| 503 CX_EXPORT CxPropertiesSource cxPropertiesCstrnSource(const char *str, size_t len); |
|
| 504 |
|
| 505 /** |
|
| 506 * Creates a properties source based on a C string. |
|
| 507 * |
|
| 508 * The length will be determined with strlen(), so the string MUST be |
|
| 509 * zero-terminated. |
|
| 510 * |
|
| 511 * @param str the string |
|
| 512 * @return the properties source |
|
| 513 * @see cxPropertiesLoad() |
|
| 514 */ |
|
| 515 cx_attr_nonnull cx_attr_nodiscard cx_attr_cstr_arg(1) |
|
| 516 CX_EXPORT CxPropertiesSource cxPropertiesCstrSource(const char *str); |
|
| 517 |
|
| 518 /** |
|
| 519 * Creates a properties source based on an FILE. |
|
| 520 * |
|
| 521 * @param file the file |
|
| 522 * @param chunk_size how many bytes may be read in one operation |
|
| 523 * |
|
| 524 * @return the properties source |
|
| 525 * @see cxPropertiesLoad() |
|
| 526 */ |
|
| 527 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1) |
|
| 528 CX_EXPORT CxPropertiesSource cxPropertiesFileSource(FILE *file, size_t chunk_size); |
|
| 529 |
|
| 530 |
|
| 531 /** |
|
| 532 * Loads properties data from a source and transfers it to a sink. |
|
| 533 * |
|
| 534 * This function tries to read as much data from the source as possible. |
|
| 535 * When the source was completely consumed and at least on k/v-pair was found, |
|
| 536 * the return value will be #CX_PROPERTIES_NO_ERROR. |
|
| 537 * When the source was consumed but no k/v-pairs were found, the return value |
|
| 538 * will be #CX_PROPERTIES_NO_DATA. |
|
| 539 * In case the source data ends unexpectedly, the #CX_PROPERTIES_INCOMPLETE_DATA |
|
| 540 * is returned. In that case you should call this function again with the same |
|
| 541 * sink and either an updated source or the same source if the source is able to |
|
| 542 * yield the missing data. |
|
| 543 * |
|
| 544 * The other result codes apply, according to their description. |
|
| 545 * |
|
| 546 * @param prop the properties interface |
|
| 547 * @param sink the sink |
|
| 548 * @param source the source |
|
| 549 * @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found |
|
| 550 * @retval CX_PROPERTIES_READ_INIT_FAILED initializing the source failed |
|
| 551 * @retval CX_PROPERTIES_READ_FAILED reading from the source failed |
|
| 552 * @retval CX_PROPERTIES_SINK_FAILED sinking the properties into the sink failed |
|
| 553 * @retval CX_PROPERTIES_NO_DATA the source did not provide any key/value pairs |
|
| 554 * @retval CX_PROPERTIES_INCOMPLETE_DATA the source did not provide enough data |
|
| 555 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
365 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
| 556 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
366 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
| 557 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
367 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
| 558 */ |
368 * @retval CX_PROPERTIES_FILE_ERROR a file operation failed; depending on the system @c errno might be set |
| 559 cx_attr_nonnull |
369 * @retval CX_PROPERTIES_MAP_ERROR storing a key/value pair in the map failed |
| 560 CX_EXPORT CxPropertiesStatus cxPropertiesLoad(CxProperties *prop, |
370 * @see cxPropertiesLoadDefault() |
| 561 CxPropertiesSink sink, CxPropertiesSource source); |
371 */ |
| |
372 #define cxPropertiesLoad(config, filename, target) cx_properties_load(config, cx_strcast(filename), target) |
| |
373 |
| |
374 /** |
| |
375 * Loads properties from a file and inserts them into a map with a default config. |
| |
376 * |
| |
377 * Entries are added to the map, possibly overwriting existing entries. |
| |
378 * |
| |
379 * The map must either store pointers of type @c char*, or elements of type cxmutstr. |
| |
380 * Any other configuration is not supported. |
| |
381 * |
| |
382 * @param filename (any string) the absolute or relative path to the file |
| |
383 * @param target (@c CxMap*) the map where the properties shall be added |
| |
384 * @retval CX_PROPERTIES_NO_ERROR (zero) at least one key/value pair was found |
| |
385 * @retval CX_PROPERTIES_NO_DATA the file is syntactically OK, but does not contain properties |
| |
386 * @retval CX_PROPERTIES_INCOMPLETE_DATA unexpected end of file |
| |
387 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
| |
388 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
| |
389 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
| |
390 * @retval CX_PROPERTIES_FILE_ERROR a file operation failed; depending on the system @c errno might be set |
| |
391 * @retval CX_PROPERTIES_MAP_ERROR storing a key/value pair in the map failed |
| |
392 * @see cxPropertiesLoad() |
| |
393 */ |
| |
394 #define cxPropertiesLoadDefault(filename, target) cx_properties_load(cx_properties_config_default, cx_strcast(filename), target) |
| |
395 |
| 562 |
396 |
| 563 #ifdef __cplusplus |
397 #ifdef __cplusplus |
| 564 } // extern "C" |
398 } // extern "C" |
| 565 #endif |
399 #endif |
| 566 |
400 |