save
[protos/libecoli.git] / lib / ecoli_tk_int.c
index 41ed54a..bd0155d 100644 (file)
 #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;
@@ -45,54 +54,69 @@ static size_t parse_llint(struct ec_tk_int *tk, const char *str,
        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;
@@ -114,101 +138,91 @@ long long ec_tk_int_getval(struct ec_tk *gen_tk, const char *str)
        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);