From 75cbf15255eaf0e5f9a43a568272c3bacf344c07 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 1 Mar 2018 15:13:01 +0100 Subject: [PATCH] rework int/uint node --- lib/ecoli_node.c | 19 ++-- lib/ecoli_node.h | 2 +- lib/ecoli_node_int.c | 224 ++++++++++++++++++++++++++++++++++--------- lib/ecoli_node_int.h | 23 ++++- 4 files changed, 212 insertions(+), 56 deletions(-) diff --git a/lib/ecoli_node.c b/lib/ecoli_node.c index cde43b5..1c0544c 100644 --- a/lib/ecoli_node.c +++ b/lib/ecoli_node.c @@ -95,11 +95,9 @@ struct ec_node *__ec_node(const struct ec_node_type *type, const char *id) node->type = type; node->refcnt = 1; - if (id != NULL) { - node->id = ec_strdup(id); - if (node->id == NULL) - goto fail; - } + node->id = ec_strdup(id); + if (node->id == NULL) + goto fail; snprintf(buf, sizeof(buf), "<%s>", type->name); node->desc = ec_strdup(buf); // XXX ec_asprintf ? @@ -110,10 +108,19 @@ struct ec_node *__ec_node(const struct ec_node_type *type, const char *id) if (node->attrs == NULL) goto fail; + if (type->init_priv != NULL) { + if (type->init_priv(node) < 0) + goto fail; + } + return node; fail: - ec_node_free(node); + ec_keyval_free(node->attrs); + ec_free(node->desc); + ec_free(node->id); + ec_free(node); + return NULL; } diff --git a/lib/ecoli_node.h b/lib/ecoli_node.h index ebd8323..d4f65f3 100644 --- a/lib/ecoli_node.h +++ b/lib/ecoli_node.h @@ -101,7 +101,7 @@ typedef int (*ec_node_complete_t)(const struct ec_node *node, const struct ec_strvec *strvec); typedef size_t (*ec_node_get_max_parse_len_t)(const struct ec_node *node); typedef const char * (*ec_node_desc_t)(const struct ec_node *); -typedef void (*ec_node_init_priv_t)(struct ec_node *); +typedef int (*ec_node_init_priv_t)(struct ec_node *); typedef void (*ec_node_free_priv_t)(struct ec_node *); /** diff --git a/lib/ecoli_node_int.c b/lib/ecoli_node_int.c index cf81fb6..45786fa 100644 --- a/lib/ecoli_node_int.c +++ b/lib/ecoli_node_int.c @@ -45,7 +45,8 @@ EC_LOG_TYPE_REGISTER(node_int); -struct ec_node_int { +/* common to int and uint */ +struct ec_node_int_uint { struct ec_node gen; bool is_signed; bool check_min; @@ -61,7 +62,7 @@ struct ec_node_int { unsigned int base; }; -static int parse_llint(struct ec_node_int *node, const char *str, +static int parse_llint(struct ec_node_int_uint *node, const char *str, int64_t *val) { char *endptr; @@ -87,7 +88,7 @@ static int parse_llint(struct ec_node_int *node, const char *str, return 0; } -static int parse_ullint(struct ec_node_int *node, const char *str, +static int parse_ullint(struct ec_node_int_uint *node, const char *str, uint64_t *val) { char *endptr; @@ -118,11 +119,11 @@ static int parse_ullint(struct ec_node_int *node, const char *str, return 0; } -static int ec_node_int_parse(const struct ec_node *gen_node, +static int ec_node_int_uint_parse(const struct ec_node *gen_node, struct ec_parsed *state, const struct ec_strvec *strvec) { - struct ec_node_int *node = (struct ec_node_int *)gen_node; + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; const char *str; int64_t val; @@ -138,18 +139,29 @@ static int ec_node_int_parse(const struct ec_node *gen_node, return 1; } -static size_t ec_node_int_get_max_parse_len(const struct ec_node *gen_node) +static size_t ec_node_int_uint_get_max_parse_len(const struct ec_node *gen_node) { (void)gen_node; return 1; } +static int +ec_node_uint_init_priv(struct ec_node *gen_node) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + + node->is_signed = true; + + return 0; +} + static struct ec_node_type ec_node_int_type = { .name = "int", - .parse = ec_node_int_parse, + .parse = ec_node_int_uint_parse, .complete = ec_node_default_complete, - .get_max_parse_len = ec_node_int_get_max_parse_len, - .size = sizeof(struct ec_node_int), + .get_max_parse_len = ec_node_int_uint_get_max_parse_len, + .size = sizeof(struct ec_node_int_uint), + .init_priv = ec_node_uint_init_priv, }; EC_NODE_TYPE_REGISTER(ec_node_int_type); @@ -158,75 +170,189 @@ struct ec_node *ec_node_int(const char *id, int64_t min, int64_t max, unsigned int base) { struct ec_node *gen_node = NULL; - struct ec_node_int *node = NULL; - if (min > max) + gen_node = __ec_node(&ec_node_int_type, id); + if (gen_node == NULL) return NULL; - gen_node = __ec_node(&ec_node_int_type, id); + if (ec_node_int_set_limits(gen_node, min, max) < 0) + goto fail; + if (ec_node_int_set_base(gen_node, base) < 0) + goto fail; + + return gen_node; + +fail: + ec_node_free(gen_node); + return NULL; +} + +static struct ec_node_type ec_node_uint_type = { + .name = "uint", + .parse = ec_node_int_uint_parse, + .complete = ec_node_default_complete, + .get_max_parse_len = ec_node_int_uint_get_max_parse_len, + .size = sizeof(struct ec_node_int_uint), +}; + +EC_NODE_TYPE_REGISTER(ec_node_uint_type); + +struct ec_node *ec_node_uint(const char *id, uint64_t min, + uint64_t max, unsigned int base) +{ + struct ec_node *gen_node = NULL; + + gen_node = __ec_node(&ec_node_uint_type, id); if (gen_node == NULL) return NULL; - node = (struct ec_node_int *)gen_node; + + if (ec_node_uint_set_limits(gen_node, min, max) < 0) + goto fail; + if (ec_node_uint_set_base(gen_node, base) < 0) + goto fail; + + return gen_node; + +fail: + ec_node_free(gen_node); + return NULL; +} + +int ec_node_int_disable_limits(struct ec_node *gen_node) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; + + ret = ec_node_check_type(gen_node, &ec_node_int_type); + if (ret < 0) + return ret; + + node->check_min = false; + node->check_max = false; + + return 0; +} + +int ec_node_int_set_limits(struct ec_node *gen_node, int64_t min, + int64_t max) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; + + ret = ec_node_check_type(gen_node, &ec_node_int_type); + if (ret < 0) + return ret; + + if (min > max) { + errno = EINVAL; + return -1; + } node->check_min = true; node->min = min; node->check_max = true; node->max = max; + + return 0; +} + +int ec_node_int_set_base(struct ec_node *gen_node, unsigned int base) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; + + ret = ec_node_check_type(gen_node, &ec_node_int_type); + if (ret < 0) + return ret; + node->base = base; - node->is_signed = true; - return &node->gen; + return 0; + } -struct ec_node *ec_node_uint(const char *id, uint64_t min, - uint64_t max, unsigned int base) +int ec_node_uint_disable_limits(struct ec_node *gen_node) { - struct ec_node *gen_node = NULL; - struct ec_node_int *node = NULL; + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; - if (min > max) - return NULL; + ret = ec_node_check_type(gen_node, &ec_node_uint_type); + if (ret < 0) + return ret; - gen_node = __ec_node(&ec_node_int_type, id); - if (gen_node == NULL) - return NULL; - node = (struct ec_node_int *)gen_node; + node->check_min = false; + node->check_max = false; + + return 0; +} + +int ec_node_uint_set_limits(struct ec_node *gen_node, uint64_t min, + uint64_t max) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; + + ret = ec_node_check_type(gen_node, &ec_node_uint_type); + if (ret < 0) + return ret; + + if (min > max) { + errno = EINVAL; + return -1; + } node->check_min = true; node->min = min; node->check_max = true; node->max = max; + + return 0; +} + +int ec_node_uint_set_base(struct ec_node *gen_node, unsigned int base) +{ + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; + + ret = ec_node_check_type(gen_node, &ec_node_uint_type); + if (ret < 0) + return ret; + node->base = base; - node->is_signed = true; - return &node->gen; + return 0; } -int64_t ec_node_int_getval(struct ec_node *gen_node, const char *str) +int ec_node_int_getval(const struct ec_node *gen_node, const char *str, + int64_t *result) { - struct ec_node_int *node = (struct ec_node_int *)gen_node; - int64_t val = 0; + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; - // XXX check type here - // if gen_node->type != int fail - // we may need to change the API (return int + val in a ptr ?) + ret = ec_node_check_type(gen_node, &ec_node_int_type); + if (ret < 0) + return ret; - parse_llint(node, str, &val); + if (parse_llint(node, str, result) < 0) + return -1; - return val; + return 0; } -uint64_t ec_node_uint_getval(struct ec_node *gen_node, const char *str) +int ec_node_uint_getval(const struct ec_node *gen_node, const char *str, + uint64_t *result) { - struct ec_node_int *node = (struct ec_node_int *)gen_node; - uint64_t val = 0; + struct ec_node_int_uint *node = (struct ec_node_int_uint *)gen_node; + int ret; - // XXX check type here - // if gen_node->type != int fail + ret = ec_node_check_type(gen_node, &ec_node_uint_type); + if (ret < 0) + return ret; - parse_ullint(node, str, &val); + if (parse_ullint(node, str, result) < 0) + return -1; - return val; + return 0; } /* LCOV_EXCL_START */ @@ -236,6 +362,8 @@ static int ec_node_int_testcase(void) struct ec_node *node; const char *s; int ret = 0; + uint64_t u64; + int64_t i64; node = ec_node_uint(EC_NO_ID, 0, 256, 0); if (node == NULL) { @@ -251,12 +379,16 @@ static int ec_node_int_testcase(void) p = ec_node_parse(node, "0"); s = ec_strvec_val(ec_parsed_strvec(p), 0); - EC_TEST_ASSERT(s != NULL && ec_node_int_getval(node, s) == 0); + EC_TEST_ASSERT(s != NULL && + ec_node_int_getval(node, s, &i64) == 0 && + i64 == 0); ec_parsed_free(p); p = ec_node_parse(node, "10"); s = ec_strvec_val(ec_parsed_strvec(p), 0); - EC_TEST_ASSERT(s != NULL && ec_node_uint_getval(node, s) == 10); + EC_TEST_ASSERT(s != NULL && + ec_node_uint_getval(node, s, &u64) == 0 && + u64 == 10); ec_parsed_free(p); ec_node_free(node); @@ -273,7 +405,9 @@ static int ec_node_int_testcase(void) p = ec_node_parse(node, "10"); s = ec_strvec_val(ec_parsed_strvec(p), 0); - EC_TEST_ASSERT(s != NULL && ec_node_int_getval(node, s) == 16); + EC_TEST_ASSERT(s != NULL && + ec_node_int_getval(node, s, &i64) == 0 && + i64 == 16); ec_parsed_free(p); ec_node_free(node); diff --git a/lib/ecoli_node_int.h b/lib/ecoli_node_int.h index b871529..01a0618 100644 --- a/lib/ecoli_node_int.h +++ b/lib/ecoli_node_int.h @@ -32,16 +32,31 @@ #include -// XXX remove min, max, base from new(), and add ec_node_int_set_limits() + -// XXX ec_node_int_set_base() ? +/* ec_node("int", ...) can be used too + * default is no limit, base 10 */ struct ec_node *ec_node_int(const char *id, int64_t min, int64_t max, unsigned int base); -int64_t ec_node_int_getval(struct ec_node *node, const char *str); + +int ec_node_int_disable_limits(struct ec_node *node); +int ec_node_int_set_limits(struct ec_node *node, int64_t min, + int64_t max); +int ec_node_int_set_base(struct ec_node *node, unsigned int base); + +int ec_node_int_getval(const struct ec_node *node, const char *str, + int64_t *result); + + struct ec_node *ec_node_uint(const char *id, uint64_t min, uint64_t max, unsigned int base); -uint64_t ec_node_uint_getval(struct ec_node *node, const char *str); +int ec_node_uint_disable_limits(struct ec_node *node); +int ec_node_uint_set_limits(struct ec_node *node, uint64_t min, + uint64_t max); +int ec_node_uint_set_base(struct ec_node *node, unsigned int base); + +int ec_node_uint_getval(const struct ec_node *node, const char *str, + uint64_t *result); #endif -- 2.39.5