#include <ctype.h>
#include <errno.h>
+#include <ecoli_log.h>
#include <ecoli_malloc.h>
+#include <ecoli_strvec.h>
#include <ecoli_tk.h>
#include <ecoli_tk_int.h>
#include <ecoli_test.h>
-static size_t parse_llint(struct ec_tk_int *tk, const char *str,
+struct ec_tk_int {
+ struct ec_tk gen;
+ long long int min;
+ long long int max;
+ unsigned int base;
+};
+
+static int parse_llint(struct ec_tk_int *tk, const char *str,
long long *val)
{
char *endptr;
errno = 0;
*val = strtoll(str, &endptr, tk->base);
- /* starts with a space */
- if (isspace(str[0]))
- return 0;
-
/* out of range */
if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) ||
(errno != 0 && *val == 0))
- return 0;
+ return -1;
if (*val < tk->min || *val > tk->max)
- return 0;
+ return -1;
- return endptr - str;
+ if (*endptr != 0)
+ return -1;
+
+ return 0;
}
-static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk,
- const char *str)
+static struct ec_parsed_tk *ec_tk_int_parse(const struct ec_tk *gen_tk,
+ const struct ec_strvec *strvec)
{
struct ec_tk_int *tk = (struct ec_tk_int *)gen_tk;
struct ec_parsed_tk *parsed_tk;
+ struct ec_strvec *match_strvec;
+ const char *str;
long long val;
- size_t len;
-
- len = parse_llint(tk, str, &val);
- if (len == 0)
- return NULL;
- parsed_tk = ec_parsed_tk_new(gen_tk);
+ parsed_tk = ec_parsed_tk_new();
if (parsed_tk == NULL)
- return NULL;
+ goto fail;
+
+ if (ec_strvec_len(strvec) == 0)
+ return parsed_tk;
- parsed_tk->str = ec_strndup(str, len);
+ str = ec_strvec_val(strvec, 0);
+ if (parse_llint(tk, str, &val) < 0)
+ return parsed_tk;
+
+ match_strvec = ec_strvec_ndup(strvec, 0, 1);
+ if (match_strvec == NULL)
+ goto fail;
+
+ ec_parsed_tk_set_match(parsed_tk, gen_tk, match_strvec);
return parsed_tk;
+
+ fail:
+ ec_parsed_tk_free(parsed_tk);
+ return NULL;
}
-static struct ec_tk_ops int_ops = {
- .parse = parse,
+static struct ec_tk_ops ec_tk_int_ops = {
+ .typename = "int",
+ .parse = ec_tk_int_parse,
+ .complete = ec_tk_default_complete,
};
-struct ec_tk *ec_tk_int_new(const char *id, long long int min,
+struct ec_tk *ec_tk_int(const char *id, long long int min,
long long int max, unsigned int base)
{
+ struct ec_tk *gen_tk = NULL;
struct ec_tk_int *tk = NULL;
- tk = (struct ec_tk_int *)ec_tk_new(id, &int_ops, sizeof(*tk));
- if (tk == NULL)
+ gen_tk = ec_tk_new(id, &ec_tk_int_ops, sizeof(*tk));
+ if (gen_tk == NULL)
return NULL;
+ tk = (struct ec_tk_int *)gen_tk;
tk->min = min;
tk->max = max;
return val;
}
-static int testcase(void)
+static int ec_tk_int_testcase(void)
{
struct ec_parsed_tk *p;
struct ec_tk *tk;
const char *s;
int ret = 0;
- tk = ec_tk_int_new(NULL, 0, 256, 0);
+ tk = ec_tk_int(NULL, 0, 256, 0);
if (tk == NULL) {
- printf("cannot create tk\n");
+ ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
}
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "256", "256");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x100", "0x100");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", NULL);
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x101", NULL);
- ret |= EC_TEST_CHECK_TK_PARSE(tk, " 1", NULL);
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "0");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "256", "foo");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "0x100");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, " 1");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "-1");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "0x101");
p = ec_tk_parse(tk, "0");
- s = ec_parsed_tk_to_string(p);
- if (s == NULL) {
- TEST_ERR();
- } else {
- if (ec_tk_int_getval(tk, s) != 0)
- TEST_ERR();
- }
+ s = ec_strvec_val(ec_parsed_tk_strvec(p), 0);
+ EC_TEST_ASSERT(s != NULL && ec_tk_int_getval(tk, s) == 0);
ec_parsed_tk_free(p);
p = ec_tk_parse(tk, "10");
- s = ec_parsed_tk_to_string(p);
- if (s == NULL) {
- TEST_ERR();
- } else {
- if (ec_tk_int_getval(tk, s) != 10)
- TEST_ERR();
- }
+ s = ec_strvec_val(ec_parsed_tk_strvec(p), 0);
+ EC_TEST_ASSERT(s != NULL && ec_tk_int_getval(tk, s) == 10);
ec_parsed_tk_free(p);
ec_tk_free(tk);
- tk = ec_tk_int_new(NULL, -1, LLONG_MAX, 16);
+ tk = ec_tk_int(NULL, -1, LLONG_MAX, 16);
if (tk == NULL) {
- printf("cannot create tk\n");
+ ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
}
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", "-1");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "7fffffffffffffff",
- "7fffffffffffffff");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x7fffffffffffffff",
- "0x7fffffffffffffff");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "-2", NULL);
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "0");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "-1");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "7fffffffffffffff");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "0x7fffffffffffffff");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "-2");
p = ec_tk_parse(tk, "10");
- s = ec_parsed_tk_to_string(p);
- if (s == NULL) {
- TEST_ERR();
- } else {
- if (ec_tk_int_getval(tk, s) != 16)
- TEST_ERR();
- }
+ s = ec_strvec_val(ec_parsed_tk_strvec(p), 0);
+ EC_TEST_ASSERT(s != NULL && ec_tk_int_getval(tk, s) == 16);
ec_parsed_tk_free(p);
ec_tk_free(tk);
- tk = ec_tk_int_new(NULL, LLONG_MIN, 0, 10);
+ tk = ec_tk_int(NULL, LLONG_MIN, 0, 10);
if (tk == NULL) {
- printf("cannot create tk\n");
+ ec_log(EC_LOG_ERR, "cannot create tk\n");
return -1;
}
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", "-1");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "-9223372036854775808",
- "-9223372036854775808");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x0", "0");
- ret |= EC_TEST_CHECK_TK_PARSE(tk, "1", NULL);
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "0");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "-1");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, 1, "-9223372036854775808");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "0x0");
+ ret |= EC_TEST_CHECK_TK_PARSE(tk, -1, "1");
ec_tk_free(tk);
- /* /\* test completion *\/ */
- /* tk = ec_tk_int_new(NULL, "foo"); */
- /* if (tk == NULL) { */
- /* printf("cannot create tk\n"); */
- /* return -1; */
- /* } */
- /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo"); */
- /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "f", "oo"); */
- /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "foo", ""); */
- /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "x", NULL); */
- /* ec_tk_free(tk); */
+ /* test completion */
+ tk = ec_tk_int(NULL, 0, 10, 0);
+ if (tk == NULL) {
+ ec_log(EC_LOG_ERR, "cannot create tk\n");
+ return -1;
+ }
+ ret |= EC_TEST_CHECK_TK_COMPLETE(tk,
+ "", EC_TK_ENDLIST,
+ EC_TK_ENDLIST,
+ "");
+ ret |= EC_TEST_CHECK_TK_COMPLETE(tk,
+ "x", EC_TK_ENDLIST,
+ EC_TK_ENDLIST,
+ "");
+ ret |= EC_TEST_CHECK_TK_COMPLETE(tk,
+ "1", EC_TK_ENDLIST,
+ EC_TK_ENDLIST,
+ "");
+ ec_tk_free(tk);
return ret;
}
-static struct ec_test test = {
+static struct ec_test ec_tk_int_test = {
.name = "tk_int",
- .test = testcase,
+ .test = ec_tk_int_testcase,
};
-EC_REGISTER_TEST(test);
+EC_REGISTER_TEST(ec_tk_int_test);