From ee7e2dbf3d6bc4ef8d4019c666a8960976c1af75 Mon Sep 17 00:00:00 2001 From: pommicket Date: Sun, 14 Sep 2025 12:53:39 -0400 Subject: Parse uint --- examples/conf.pom | 9 ++------- examples/read_conf.c | 21 +++++---------------- pom.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ pom.h | 20 ++++++++++++++++++++ 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/examples/conf.pom b/examples/conf.pom index ed37ed9..6b839d1 100644 --- a/examples/conf.pom +++ b/examples/conf.pom @@ -1,7 +1,2 @@ -[number]p -one = 1 -two = 2x"\? -three j= "3 -is -the - best" +[number] +best = "0x127432" diff --git a/examples/read_conf.c b/examples/read_conf.c index 18802e3..c4cabfc 100644 --- a/examples/read_conf.c +++ b/examples/read_conf.c @@ -12,21 +12,10 @@ int main(int argc, char **argv) { free(error); return EXIT_FAILURE; } - pom_conf *conf2 = pom_load_string("", "foo=bar\r\n[j.number]\n" - "one = I\n" - "five = V\n", &error); - if (!conf2) { - pom_conf_free(conf); - pom_error_print(error); - free(error); - return EXIT_FAILURE; - } - pom_conf *copy = pom_conf_copy(conf); - pom_conf_merge(copy,pom_conf_section(conf2,"j")); - pom_conf *copy2 = pom_conf_copy(copy); - pom_conf_print(copy2); + uint64_t value; + const char *s = pom_conf_get_uint(conf, "number.best", &value); + printf("%" PRIu64 "\n", value); + if (s) printf(" -> %s\n",s); + pom_conf_print(conf); pom_conf_free(conf); - pom_conf_free(copy); - pom_conf_free(copy2); - pom_conf_free(conf2); } diff --git a/pom.c b/pom.c index ad3919c..87154e8 100644 --- a/pom.c +++ b/pom.c @@ -1535,3 +1535,53 @@ pom_conf_copy(const pom_conf *conf) { } return new_root; } + +static bool +parse_uint(const char *s, uint64_t *val) { + if (*s == '+') s++; + if (*s == 0) { + // empty number + return false; + } + uint64_t value = 0; + if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { + // hexadecimal + for (size_t i = 2; s[i]; i++) { + if (parse_hex_digit(s[i]) == -1) + return false; + } + value = (uint64_t) strtoull(s, NULL, 16); + } else if (*s == '0') { + if (s[1] != 0) { + // leading zero + return false; + } + } else { + for (size_t i = 0; s[i]; i++) { + if (s[i] < '0' || s[i] > '9') + return false; + } + value = (uint64_t) strtoull(s, NULL, 10); + } + if (value >> 53) { + // too big! + return false; + } + *val = value; + return true; +} + +const char * +pom_conf_get_uint(const pom_conf *conf, const char *key, uint64_t *value_uint) { + check_conf(conf); + if (!key) fatal_error("NULL key passed to %s", __func__); + if (!value_uint) fatal_error("NULL value passed to %s", __func__); + *value_uint = 0; + const char *value_str = pom_conf_get(conf, key); + if (!value_str) { + return ""; + } + if (parse_uint(value_str, value_uint)) + return NULL; + return value_str; +} diff --git a/pom.h b/pom.h index 1139ee8..5635316 100644 --- a/pom.h +++ b/pom.h @@ -230,10 +230,14 @@ 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. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get(const pom_conf *conf, const char *key); /// Get value of `key` in configuration, or use `dflt` if not present. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_or_default(const pom_conf *conf, const char *key, const char *dflt); @@ -246,6 +250,8 @@ pom_conf_get_or_default(const pom_conf *conf, const char *key, const char *dflt) /// (decimal or `0x`/`0X`-prefixed hexadecimal, absolute value less than 253), /// returns the value of `key`. /// `*value` is set to 0 in these cases. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_int(const pom_conf *conf, const char *key, int64_t *value); @@ -257,6 +263,8 @@ pom_conf_get_int(const pom_conf *conf, const char *key, int64_t *value); /// (decimal or `0x`/`0X`-prefixed hexadecimal, absolute value less than 253), /// returns the value of `key`. /// `*value` is still set to `dflt` in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_int_or_default(const pom_conf *conf, const char *key, int64_t *value, int64_t dflt); @@ -268,6 +276,8 @@ pom_conf_get_int_or_default(const pom_conf *conf, const char *key, int64_t *valu /// (decimal or `0x`/`0X`-prefixed hexadecimal, less than 253), /// returns the value of `key`. /// `*value` is set to 0 in these case cases. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_uint(const pom_conf *conf, const char *key, uint64_t *value); @@ -279,6 +289,8 @@ pom_conf_get_uint(const pom_conf *conf, const char *key, uint64_t *value); /// (decimal or `0x`/`0X`-prefixed hexadecimal, less than 253), /// returns the value of `key`. /// `*value` is set to 0 in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_uint_or_default(const pom_conf *conf, const char *key, uint64_t *value, uint64_t dflt); @@ -289,6 +301,8 @@ pom_conf_get_uint_or_default(const pom_conf *conf, const char *key, uint64_t *va /// If `key` is not set, returns `""`. If `key` is set but not a valid floating-point number, /// returns the value of `key`. /// `*value` is set to 0.0 in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_float(const pom_conf *conf, const char *key, double *value); @@ -299,6 +313,8 @@ pom_conf_get_float(const pom_conf *conf, const char *key, double *value); /// If `key` is set but not a valid floating-point number, /// returns the value of `key`. /// `*value` is still set to `dflt` in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_float_or_default(const pom_conf *conf, const char *key, double *value, double dflt); @@ -310,6 +326,8 @@ pom_conf_get_float_or_default(const pom_conf *conf, const char *key, double *val /// (`off`/`false`/`no`/`on`/`true`/`yes`), /// returns the value of `key`. /// `*value` is set to `false` in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_bool(const pom_conf *conf, const char *key, bool *value); @@ -321,6 +339,8 @@ pom_conf_get_bool(const pom_conf *conf, const char *key, bool *value); /// (`off`/`false`/`no`/`on`/`true`/`yes`), /// returns the value of `key`. /// `*value` is still set to `dflt` in this case. +/// +/// The returned pointer is valid until \ref pom_conf_free is called. const char * pom_conf_get_bool_or_default(const pom_conf *conf, const char *key, bool *value, bool dflt); -- cgit v1.2.3