diff options
author | pommicket <pommicket@gmail.com> | 2025-09-11 13:25:17 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-09-11 13:25:17 -0400 |
commit | 4dbbeb1e85390d7c5e24fce4e61c8d29dda6aa00 (patch) | |
tree | b0ec0700bdb824bfbc4db54029f3619ae2a5df74 /pom.h | |
parent | 7b8b6367492453958dd0eff6a264ca003002c4b5 (diff) |
Add iterators
Diffstat (limited to 'pom.h')
-rw-r--r-- | pom.h | 160 |
1 files changed, 151 insertions, 9 deletions
@@ -10,7 +10,7 @@ /// Other than that, all these functions are fully thread-safe /// provided that C11 atomics are available /// (`__STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)`). -/// But beware of race conditions when using \ref pom_conf_unread_keys +/// But beware of race conditions when using \ref pom_conf_next_unread_key /// (ensure there is synchronization so that all threads /// have certainly read their keys before calling it). /// @@ -49,9 +49,37 @@ /// A POM configuration typedef struct pom_conf pom_conf; + /// A POM-related error typedef struct pom_error pom_error; +/// An opaque iterator produced by \ref pom_conf_next_unread_key. +typedef struct pom_unread_key_iter pom_unread_key_iter; + +/// An opaque iterator produced by \ref pom_conf_next_item. +typedef struct pom_item_iter pom_item_iter; + +/// An opaque iterator produced by \ref pom_conf_next_key. +typedef struct pom_key_iter pom_key_iter; + +/// Item returned by \ref pom_conf_next_item +typedef struct pom_item { + /// The key. + /// + /// This pointer is valid until \ref pom_conf_free is called. + const char *key; + /// The value of the key. + /// + /// This pointer is valid until \ref pom_conf_free is called. + const char *val; + /// The file where the key was defined. + /// + /// This pointer is valid until \ref pom_conf_free is called. + const char *file; + /// The line number where the key was defined. + uint64_t line; +} pom_item; + /// Load a configuration using a `read`-like function. /// /// On success, a configuration is returned and `*error` is set to `NULL` @@ -81,6 +109,7 @@ pom_load(const char *filename, size_t (*read_func)(void *userdata, char *buf, size_t len), void *userdata, pom_error **error) POM__MUST_USE_R; + #ifndef POM_NO_STDIO /// Load configuration from a `FILE *`. /// @@ -95,6 +124,7 @@ POM__MUST_USE_L pom_conf * pom_load_file(const char *filename, FILE *file, pom_error **error) POM__MUST_USE_R; + /// Load configuration from a file path. /// /// On success, a configuration is returned and `*error` is set to `NULL` @@ -107,6 +137,7 @@ pom_conf * pom_load_path(const char *path, pom_error **error) POM__MUST_USE_R; #endif + /// Load configuration from a string. /// /// On success, a configuration is returned and `*error` is set to `NULL` @@ -120,6 +151,7 @@ POM__MUST_USE_L pom_conf * pom_load_string(const char *filename, const char *string, pom_error **error) POM__MUST_USE_R; + /// Get the message of this error. /// /// This will be a string such as `"Duplicate key: foo.bar"` @@ -128,15 +160,19 @@ POM__MUST_USE_R; /// are probably actually what you want in most cases. const char * pom_error_message(const pom_error *error); + /// Get the name of the file where this error occured. const char * pom_error_file(const pom_error *error); + /// Get line number where this error occured. uint64_t pom_error_line(const pom_error *error); + /// Get next error in error list. const pom_error * pom_error_next(const pom_error *error); + #ifndef POM_NO_STDIO /// Print error to `stderr`. /// @@ -144,6 +180,7 @@ pom_error_next(const pom_error *error); void pom_error_print(const pom_error *error); #endif + /// Convert error to string. Return value must be `free()`d. /// /// Includes every error in an error list (see \ref pom_error_next). @@ -151,12 +188,30 @@ POM__MUST_USE_L char * pom_error_to_string(const pom_error *error) POM__MUST_USE_R; + +/// Returns `true` if `key` is present in `conf`, `false` otherwise. +bool +pom_conf_has(const pom_conf *conf, const char *key); + +/// Get location where `key` was defined in `conf`. +/// +/// Returns `true` and sets `*file` and `*line` if the `key` is present. +/// The pointer which `*file` is set to is valid until \ref pom_conf_free is called. +/// +/// Returns `false` and sets `*file = NULL`, `*line = 0` if `key` is not present. +/// +/// Either of `file`, `line` may be `NULL`, in which case it is not set. +bool +pom_conf_location(const pom_conf *conf, const char *key, const char **file, uint64_t *line); + /// Get value of `key` in configuration, or `NULL` if key is not present. const char * pom_conf_get(const pom_conf *conf, const char *key); + /// Get value of `key` in configuration, or use `dflt` if not present. const char * pom_conf_get_or_default(const pom_conf *conf, const char *key, const char *dflt); + /// Get signed integer value of `key`. /// /// Returns `NULL` on success, putting the integer value in `*value`. @@ -168,6 +223,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_int(const pom_conf *conf, const char *key, int64_t *value) POM__MUST_USE_R; + /// Get signed integer value of `key`, or `dflt` if not present. /// /// Returns `NULL` on success, putting the integer value in `*value`. @@ -179,6 +235,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_int_or_default(const pom_conf *conf, const char *key, int64_t *value, int64_t dflt) POM__MUST_USE_R; + /// Get unsigned integer value of `key`. /// /// Returns `NULL` on success, putting the unsigned integer value in `*value`. @@ -190,6 +247,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_uint(const pom_conf *conf, const char *key, uint64_t *value) POM__MUST_USE_R; + /// Get unsigned integer value of `key`, or `dflt` if not present. /// /// Returns `NULL` on success, putting the unsigned integer value in `*value`. @@ -201,6 +259,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_uint_or_default(const pom_conf *conf, const char *key, uint64_t *value, uint64_t dflt) POM__MUST_USE_R; + /// Get floating-point value of `key`. /// /// Returns `NULL` on success, putting the floating-point value in `*value`. @@ -212,6 +271,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_float(const pom_conf *conf, const char *key, double *value) POM__MUST_USE_R; + /// Get floating-point value of `key`, or `dflt` if not present. /// /// Returns `NULL` on success, putting the floating-point value in `*value`. @@ -223,6 +283,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_float_or_default(const pom_conf *conf, const char *key, double *value, double dflt) POM__MUST_USE_R; + /// Get boolean value of `key`. /// /// Returns `NULL` on success, putting the boolean value in `*value`. @@ -234,6 +295,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_bool(const pom_conf *conf, const char *key, bool *value) POM__MUST_USE_R; + /// Get boolean value of `key`, or `dflt` if not present. /// /// Returns `NULL` on success, putting the boolean value in `*value`. @@ -245,6 +307,7 @@ POM__MUST_USE_L pom_error * pom_conf_get_bool_or_default(const pom_conf *conf, const char *key, bool *value, bool dflt) POM__MUST_USE_R; + /// Get comma-separated list value of `key`, or `NULL` if not present. The return value must be freed with `free`. /// /// The list is `NULL`-terminated. @@ -257,12 +320,72 @@ POM__MUST_USE_L char ** pom_conf_get_list(const pom_conf *conf, const char *key) POM__MUST_USE_R; + /// Extract section out of POM configuration. /// +/// Specifically, this returns the configuration consisting of all keys +/// prefixed by `section.`, with that prefix removed, and their corresponding +/// values. +/// /// The returned section doesn't need to be freed, and is valid until /// \ref pom_conf_free is called on the original configuration. const pom_conf * pom_conf_section(const pom_conf *conf, const char *section); + +/// Get all ‘direct’ keys in `conf` (i.e. all first components of defined keys). +/// +/// The first call to this function should be with `*iter = NULL`. +/// Each time it is called with the same `iter`, it returns the next +/// direct key in the `conf`. +/// After all direct keys have been returned (or if an out-of-memory error occurs), +/// `NULL` is returned, any memory +/// associated with the iterator is freed, and `*iter` is set to `NULL`. +/// This function may modify `*iter` arbitrarily — do not attempt +/// to copy `*iter` or compare it with other iterators. +/// The keys are returned in an arbitrary order that may change in future versions. +/// If you decide to stop iterating halfway through, +/// you should still call this function repeatedly until you get `NULL`; +/// otherwise memory associated with the iterator may be leaked. +/// +/// The correct usage for this function is: +/// +/// ```C +/// pom_key_iter *iter = NULL; +/// const char *key; +/// while ((key = pom_conf_next_key(conf, &iter))) { +/// printf("Key: %s\n", key); +/// } +/// ``` +const char * +pom_conf_next_key(const pom_conf *conf, pom_key_iter **iter); + +/// Get all key-value pairs in `conf`. +/// +/// The first call to this function should be with `*iter = NULL`. +/// Each time it is called with the same `iter`, it returns the next +/// key-value pair in `conf`. +/// After all items have been returned (or if an out-of-memory error occurs), +/// `NULL` is returned, any memory +/// associated with the iterator is freed, and `*iter` is set to `NULL`. +/// This function may modify `*iter` arbitrarily — do not attempt +/// to copy `*iter` or compare it with other iterators. +/// The items are returned in an arbitrary order that may change in future versions. +/// If you decide to stop iterating halfway through, +/// you should still call this function repeatedly until you get `NULL`; +/// otherwise memory associated with the iterator may be leaked. +/// +/// The correct usage for this function is: +/// +/// ```C +/// pom_item_iter *iter = NULL; +/// const pom_item *item; +/// while ((item = pom_conf_next_item(conf, &iter))) { +/// printf("Key: %s, Value: %s\n", item->key, item->value); +/// } +/// ``` +const pom_item * +pom_conf_next_item(const pom_conf *conf, pom_item_iter **iter); + /// Create a copy of `conf`. /// /// The copy must be freed with \ref pom_conf_free. @@ -275,19 +398,38 @@ POM__MUST_USE_L pom_conf * pom_conf_copy(const pom_conf *conf) POM__MUST_USE_R; + /// Merge keys from `other` into `conf`, preferring keys in `other`. void pom_conf_merge(pom_conf *conf, const pom_conf *other); + /// Get all unread keys in `conf`. /// -/// The returned array is `NULL`-terminated, and must be freed with `free`. -/// -/// (The entries of the array are stored inline with the array, -/// so they are freed when it is.) -POM__MUST_USE_L -char ** -pom_conf_unread_keys(pom_conf *conf) -POM__MUST_USE_R; +/// The first call to this function should be with `*iter = NULL`. +/// Each time it is called with the same `iter`, it returns the next +/// key in the `conf` that has not been accessed with a `pom_conf_get*` function. +/// After all such keys have been returned (or if an out-of-memory error occurs), +/// `NULL` is returned, any memory +/// associated with the iterator is freed, and `*iter` is set to `NULL`. +/// This function may modify `*iter` arbitrarily — do not attempt +/// to copy `*iter` or compare it with other iterators. +/// The keys are returned in an arbitrary order that may change in future versions. +/// If you decide to stop iterating halfway through, +/// you should still call this function repeatedly until you get `NULL`; +/// otherwise memory associated with the iterator may be leaked. +/// +/// The correct usage for this function is: +/// +/// ```C +/// pom_unread_key_iter *iter = NULL; +/// const char *key; +/// while ((key = pom_conf_next_unread_key(conf, &iter))) { +/// printf("Unknown key: %s\n", key); +/// } +/// ``` +const char * +pom_conf_next_unread_key(pom_conf *conf, pom_unread_key_iter **iter); + #ifndef POM_NO_STDIO /// Print `key: value` for each `key` in `conf` to `stdout`. void |