#include <ecoli_node_int.h>
#include <ecoli_test.h>
+EC_LOG_TYPE_REGISTER(node_int);
+
struct ec_node_int {
struct ec_node gen;
+ bool is_signed;
bool check_min;
- long long int min;
bool check_max;
- long long int max;
+ union {
+ int64_t min;
+ uint64_t umin;
+ };
+ union {
+ int64_t max;
+ uint64_t umax;
+ };
unsigned int base;
};
static int parse_llint(struct ec_node_int *node, const char *str,
- long long *val)
+ int64_t *val)
{
char *endptr;
errno = 0;
*val = strtoll(str, &endptr, node->base);
- /* out of range */
- if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) ||
- (errno != 0 && *val == 0))
+ if (errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN))
+ return -1;
+
+ if (errno != 0 && *val == 0)
return -1;
if (node->check_min && *val < node->min)
return 0;
}
-static struct ec_parsed *ec_node_int_parse(const struct ec_node *gen_node,
- const struct ec_strvec *strvec)
+static int parse_ullint(struct ec_node_int *node, const char *str,
+ uint64_t *val)
+{
+ char *endptr;
+
+ /* since a negative input is silently converted to a positive
+ * one by strtoull(), first check that it is positive */
+ if (strchr(str, '-'))
+ return -1;
+
+ errno = 0;
+ *val = strtoull(str, &endptr, node->base);
+
+ if (errno == ERANGE && *val == ULLONG_MAX)
+ return -1;
+
+ if (errno != 0 && *val == 0)
+ return -1;
+
+ if (node->check_min && *val < node->umin)
+ return -1;
+
+ if (node->check_max && *val > node->umax)
+ return -1;
+
+ if (*endptr != 0)
+ return -1;
+
+ return 0;
+}
+
+static int ec_node_int_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_parsed *parsed;
- struct ec_strvec *match_strvec;
const char *str;
- long long val;
+ int64_t val;
- parsed = ec_parsed();
- if (parsed == NULL)
- goto fail;
+ (void)state;
if (ec_strvec_len(strvec) == 0)
- return parsed;
+ return EC_PARSED_NOMATCH;
str = ec_strvec_val(strvec, 0);
if (parse_llint(node, str, &val) < 0)
- return parsed;
-
- match_strvec = ec_strvec_ndup(strvec, 0, 1);
- if (match_strvec == NULL)
- goto fail;
+ return EC_PARSED_NOMATCH;
- ec_parsed_set_match(parsed, gen_node, match_strvec);
-
- return parsed;
+ return 1;
+}
- fail:
- ec_parsed_free(parsed);
- return NULL;
+static size_t ec_node_int_get_max_parse_len(const struct ec_node *gen_node)
+{
+ (void)gen_node;
+ return 1;
}
static struct ec_node_type ec_node_int_type = {
.name = "int",
.parse = ec_node_int_parse,
.complete = ec_node_default_complete,
+ .get_max_parse_len = ec_node_int_get_max_parse_len,
.size = sizeof(struct ec_node_int),
};
EC_NODE_TYPE_REGISTER(ec_node_int_type);
-struct ec_node *ec_node_int(const char *id, long long int min,
- long long int max, unsigned int base)
+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)
+ return NULL;
+
+ 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 = true;
+ node->min = min;
+ node->check_max = true;
+ node->max = max;
+ node->base = base;
+ node->is_signed = true;
+
+ return &node->gen;
+}
+
+struct ec_node *ec_node_uint(const char *id, uint64_t min,
+ uint64_t max, unsigned int base)
{
struct ec_node *gen_node = NULL;
struct ec_node_int *node = NULL;
+ if (min > max)
+ return NULL;
+
gen_node = __ec_node(&ec_node_int_type, id);
if (gen_node == NULL)
return NULL;
node->check_max = true;
node->max = max;
node->base = base;
+ node->is_signed = true;
return &node->gen;
}
-long long ec_node_int_getval(struct ec_node *gen_node, const char *str)
+int64_t ec_node_int_getval(struct ec_node *gen_node, const char *str)
{
struct ec_node_int *node = (struct ec_node_int *)gen_node;
- long long val = 0;
+ int64_t val = 0;
// XXX check type here
// if gen_node->type != int fail
return val;
}
+uint64_t ec_node_uint_getval(struct ec_node *gen_node, const char *str)
+{
+ struct ec_node_int *node = (struct ec_node_int *)gen_node;
+ uint64_t val = 0;
+
+ // XXX check type here
+ // if gen_node->type != int fail
+
+ parse_ullint(node, str, &val);
+
+ return val;
+}
+
+/* LCOV_EXCL_START */
static int ec_node_int_testcase(void)
{
struct ec_parsed *p;
const char *s;
int ret = 0;
- node = ec_node_int(NULL, 0, 256, 0);
+ node = ec_node_uint(NULL, 0, 256, 0);
if (node == NULL) {
- ec_log(EC_LOG_ERR, "cannot create node\n");
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
return -1;
}
ret |= EC_TEST_CHECK_PARSE(node, 1, "0");
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) == 10);
+ EC_TEST_ASSERT(s != NULL && ec_node_uint_getval(node, s) == 10);
ec_parsed_free(p);
ec_node_free(node);
node = ec_node_int(NULL, -1, LLONG_MAX, 16);
if (node == NULL) {
- ec_log(EC_LOG_ERR, "cannot create node\n");
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
return -1;
}
ret |= EC_TEST_CHECK_PARSE(node, 1, "0");
node = ec_node_int(NULL, LLONG_MIN, 0, 10);
if (node == NULL) {
- ec_log(EC_LOG_ERR, "cannot create node\n");
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
return -1;
}
ret |= EC_TEST_CHECK_PARSE(node, 1, "0");
/* test completion */
node = ec_node_int(NULL, 0, 10, 0);
if (node == NULL) {
- ec_log(EC_LOG_ERR, "cannot create node\n");
+ EC_LOG(EC_LOG_ERR, "cannot create node\n");
return -1;
}
ret |= EC_TEST_CHECK_COMPLETE(node,
"", EC_NODE_ENDLIST,
- EC_NODE_ENDLIST,
- "");
+ EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"x", EC_NODE_ENDLIST,
- EC_NODE_ENDLIST,
- "");
+ EC_NODE_ENDLIST);
ret |= EC_TEST_CHECK_COMPLETE(node,
"1", EC_NODE_ENDLIST,
- EC_NODE_ENDLIST,
- "");
+ EC_NODE_ENDLIST);
ec_node_free(node);
return ret;
}
+/* LCOV_EXCL_STOP */
static struct ec_test ec_node_int_test = {
.name = "node_int",