api documentation for ec_parse
[protos/libecoli.git] / src / ecoli_complete.c
index e2f150a..0d9fd95 100644 (file)
@@ -27,14 +27,39 @@ struct ec_comp_item {
        TAILQ_ENTRY(ec_comp_item) next;
        enum ec_comp_type type;
        struct ec_comp_group *grp;
-       char *start;      /* the initial token */
-       char *full;       /* the full token after completion */
-       char *completion; /* chars that are added, NULL if not applicable */
-       char *display;    /* what should be displayed by help/completers */
+       char *start;      /**< The initial token */
+       char *full;       /**< The full token after completion */
+       char *completion; /**< Chars that are added, NULL if not applicable */
+       char *display;    /**< What should be displayed by help/completers */
        struct ec_dict *attrs;
 };
 
-struct ec_comp *ec_comp(struct ec_parse *state)
+TAILQ_HEAD(ec_comp_item_list, ec_comp_item);
+
+struct ec_comp_group {
+       /* XXX counts ? */
+       TAILQ_ENTRY(ec_comp_group) next;
+       const struct ec_comp *comp;
+       const struct ec_node *node;
+       struct ec_comp_item_list items;
+       struct ec_pnode *pstate;
+       struct ec_dict *attrs;
+};
+
+TAILQ_HEAD(ec_comp_group_list, ec_comp_group);
+
+struct ec_comp {
+       size_t count;
+       size_t count_full;
+       size_t count_partial;
+       size_t count_unknown;
+       struct ec_pnode *cur_pstate;
+       struct ec_comp_group *cur_group;
+       struct ec_comp_group_list groups;
+       struct ec_dict *attrs;
+};
+
+struct ec_comp *ec_comp(void)
 {
        struct ec_comp *comp = NULL;
 
@@ -48,8 +73,6 @@ struct ec_comp *ec_comp(struct ec_parse *state)
 
        TAILQ_INIT(&comp->groups);
 
-       comp->cur_state = state;
-
        return comp;
 
  fail:
@@ -60,47 +83,58 @@ struct ec_comp *ec_comp(struct ec_parse *state)
        return NULL;
 }
 
-struct ec_parse *ec_comp_get_state(struct ec_comp *comp)
+struct ec_pnode *ec_comp_get_cur_pstate(const struct ec_comp *comp)
+{
+       return comp->cur_pstate;
+}
+
+struct ec_comp_group *ec_comp_get_cur_group(const struct ec_comp *comp)
+{
+       return comp->cur_group;
+}
+
+struct ec_dict *ec_comp_get_attrs(const struct ec_comp *comp)
 {
-       return comp->cur_state;
+       return comp->attrs;
 }
 
 int
-ec_node_complete_child(const struct ec_node *node,
+ec_complete_child(const struct ec_node *node,
                struct ec_comp *comp,
                const struct ec_strvec *strvec)
 {
-       struct ec_parse *child_state, *cur_state;
+       struct ec_pnode *child_pstate, *cur_pstate;
        struct ec_comp_group *cur_group;
+       ec_complete_t complete_cb;
        int ret;
 
-       if (ec_node_type(node)->complete == NULL) {
-               errno = ENOTSUP;
-               return -1;
-       }
+       /* get the complete method, falling back to ec_complete_unknown() */
+       complete_cb = ec_node_type(node)->complete;
+       if (complete_cb == NULL)
+               complete_cb = ec_complete_unknown;
 
        /* save previous parse state, prepare child state */
-       cur_state = comp->cur_state;
-       child_state = ec_parse(node);
-       if (child_state == NULL)
+       cur_pstate = comp->cur_pstate;
+       child_pstate = ec_pnode(node);
+       if (child_pstate == NULL)
                return -1;
 
-       if (cur_state != NULL)
-               ec_parse_link_child(cur_state, child_state);
-       comp->cur_state = child_state;
+       if (cur_pstate != NULL)
+               ec_pnode_link_child(cur_pstate, child_pstate);
+       comp->cur_pstate = child_pstate;
        cur_group = comp->cur_group;
        comp->cur_group = NULL;
 
        /* fill the comp struct with items */
-       ret = ec_node_type(node)->complete(node, comp, strvec);
+       ret = complete_cb(node, comp, strvec);
 
        /* restore parent parse state */
-       if (cur_state != NULL) {
-               ec_parse_unlink_child(cur_state, child_state);
-               assert(!ec_parse_has_child(child_state));
+       if (cur_pstate != NULL) {
+               ec_pnode_unlink_child(child_pstate);
+               assert(ec_pnode_get_first_child(child_pstate) == NULL);
        }
-       ec_parse_free(child_state);
-       comp->cur_state = cur_state;
+       ec_pnode_free(child_pstate);
+       comp->cur_pstate = cur_pstate;
        comp->cur_group = cur_group;
 
        if (ret < 0)
@@ -109,17 +143,17 @@ ec_node_complete_child(const struct ec_node *node,
        return 0;
 }
 
-struct ec_comp *ec_node_complete_strvec(const struct ec_node *node,
+struct ec_comp *ec_complete_strvec(const struct ec_node *node,
        const struct ec_strvec *strvec)
 {
        struct ec_comp *comp = NULL;
        int ret;
 
-       comp = ec_comp(NULL);
+       comp = ec_comp();
        if (comp == NULL)
                goto fail;
 
-       ret = ec_node_complete_child(node, comp, strvec);
+       ret = ec_complete_child(node, comp, strvec);
        if (ret < 0)
                goto fail;
 
@@ -130,7 +164,7 @@ fail:
        return NULL;
 }
 
-struct ec_comp *ec_node_complete(const struct ec_node *node,
+struct ec_comp *ec_complete(const struct ec_node *node,
        const char *str)
 {
        struct ec_strvec *strvec = NULL;
@@ -144,7 +178,7 @@ struct ec_comp *ec_node_complete(const struct ec_node *node,
        if (ec_strvec_add(strvec, str) < 0)
                goto fail;
 
-       comp = ec_node_complete_strvec(node, strvec);
+       comp = ec_complete_strvec(node, strvec);
        if (comp == NULL)
                goto fail;
 
@@ -157,7 +191,8 @@ struct ec_comp *ec_node_complete(const struct ec_node *node,
 }
 
 static struct ec_comp_group *
-ec_comp_group(const struct ec_node *node, struct ec_parse *parse)
+ec_comp_group(const struct ec_comp *comp, const struct ec_node *node,
+       struct ec_pnode *parse)
 {
        struct ec_comp_group *grp = NULL;
 
@@ -165,12 +200,13 @@ ec_comp_group(const struct ec_node *node, struct ec_parse *parse)
        if (grp == NULL)
                return NULL;
 
+       grp->comp = comp;
        grp->attrs = ec_dict();
        if (grp->attrs == NULL)
                goto fail;
 
-       grp->state = ec_parse_dup(parse);
-       if (grp->state == NULL)
+       grp->pstate = ec_pnode_dup(parse);
+       if (grp->pstate == NULL)
                goto fail;
 
        grp->node = node;
@@ -180,7 +216,7 @@ ec_comp_group(const struct ec_node *node, struct ec_parse *parse)
 
 fail:
        if (grp != NULL) {
-               ec_parse_free(grp->state);
+               ec_pnode_free(grp->pstate);
                ec_dict_free(grp->attrs);
        }
        ec_free(grp);
@@ -357,7 +393,7 @@ ec_comp_item_add(struct ec_comp *comp, const struct ec_node *node,
        if (comp->cur_group == NULL) {
                struct ec_comp_group *grp;
 
-               grp = ec_comp_group(node, comp->cur_state);
+               grp = ec_comp_group(comp, node, comp->cur_pstate);
                if (grp == NULL)
                        return -1;
                TAILQ_INSERT_TAIL(&comp->groups, grp, next);
@@ -421,49 +457,42 @@ ec_comp_item_free(struct ec_comp_item *item)
        ec_free(item);
 }
 
-int ec_comp_add_item(struct ec_comp *comp,
-                       const struct ec_node *node,
-                       struct ec_comp_item **p_item,
-                       enum ec_comp_type type,
-                       const char *start, const char *full)
+struct ec_comp_item *ec_comp_add_item(struct ec_comp *comp,
+               const struct ec_node *node, enum ec_comp_type type,
+               const char *start, const char *full)
 {
        struct ec_comp_item *item = NULL;
        int ret;
 
        item = ec_comp_item(type, start, full);
        if (item == NULL)
-               return -1;
+               return NULL;
 
        ret = ec_comp_item_add(comp, node, item);
        if (ret < 0)
                goto fail;
 
-       if (p_item != NULL)
-               *p_item = item;
-
-       return 0;
+       return item;
 
 fail:
        ec_comp_item_free(item);
-
-       return -1;
+       return NULL;
 }
 
 /* return a completion item of type "unknown" */
 int
-ec_node_complete_unknown(const struct ec_node *gen_node,
+ec_complete_unknown(const struct ec_node *gen_node,
                        struct ec_comp *comp,
                        const struct ec_strvec *strvec)
 {
-       int ret;
+       const struct ec_comp_item *item = NULL;
 
        if (ec_strvec_len(strvec) != 1)
                return 0;
 
-       ret = ec_comp_add_item(comp, gen_node, NULL,
-                               EC_COMP_UNKNOWN, NULL, NULL);
-       if (ret < 0)
-               return ret;
+       item = ec_comp_add_item(comp, gen_node, EC_COMP_UNKNOWN, NULL, NULL);
+       if (item == NULL)
+               return -1;
 
        return 0;
 }
@@ -480,11 +509,29 @@ static void ec_comp_group_free(struct ec_comp_group *grp)
                TAILQ_REMOVE(&grp->items, item, next);
                ec_comp_item_free(item);
        }
-       ec_parse_free(ec_parse_get_root(grp->state));
+       ec_pnode_free(ec_pnode_get_root(grp->pstate));
        ec_dict_free(grp->attrs);
        ec_free(grp);
 }
 
+const struct ec_node *
+ec_comp_group_get_node(const struct ec_comp_group *grp)
+{
+       return grp->node;
+}
+
+const struct ec_pnode *
+ec_comp_group_get_pstate(const struct ec_comp_group *grp)
+{
+       return grp->pstate;
+}
+
+const struct ec_dict *
+ec_comp_group_get_attrs(const struct ec_comp_group *grp)
+{
+       return grp->attrs;
+}
+
 void ec_comp_free(struct ec_comp *comp)
 {
        struct ec_comp_group *grp;
@@ -511,7 +558,7 @@ void ec_comp_dump(FILE *out, const struct ec_comp *comp)
                return;
        }
 
-       fprintf(out, "completion: count=%u full=%u partial=%u unknown=%u\n",
+       fprintf(out, "completion: count=%zu full=%zu partial=%zu unknown=%zu\n",
                comp->count, comp->count_full,
                comp->count_partial,  comp->count_unknown);
 
@@ -554,11 +601,9 @@ int ec_comp_merge(struct ec_comp *to,
        return 0;
 }
 
-unsigned int ec_comp_count(
-       const struct ec_comp *comp,
-       enum ec_comp_type type)
+size_t ec_comp_count(const struct ec_comp *comp, enum ec_comp_type type)
 {
-       unsigned int count = 0;
+       size_t count = 0;
 
        if (comp == NULL)
                return count;
@@ -573,76 +618,55 @@ unsigned int ec_comp_count(
        return count;
 }
 
-struct ec_comp_iter *
-ec_comp_iter(const struct ec_comp *comp,
-       enum ec_comp_type type)
-{
-       struct ec_comp_iter *iter;
-
-       iter = ec_calloc(1, sizeof(*iter));
-       if (iter == NULL)
-               return NULL;
-
-       iter->comp = comp;
-       iter->type = type;
-       iter->cur_node = NULL;
-       iter->cur_match = NULL;
-
-       return iter;
-}
-
-struct ec_comp_item *ec_comp_iter_next(
-       struct ec_comp_iter *iter)
+static struct ec_comp_item *
+__ec_comp_iter_next(const struct ec_comp *comp, struct ec_comp_item *item,
+               enum ec_comp_type type)
 {
-       const struct ec_comp *comp;
-       struct ec_comp_group *cur_node;
+       struct ec_comp_group *cur_grp;
        struct ec_comp_item *cur_match;
 
-       if (iter == NULL)
-               return NULL;
-       comp = iter->comp;
-       if (comp == NULL)
-               return NULL;
-
-       cur_node = iter->cur_node;
-       cur_match = iter->cur_match;
-
        /* first call */
-       if (cur_node == NULL) {
-               TAILQ_FOREACH(cur_node, &comp->groups, next) {
-                       TAILQ_FOREACH(cur_match, &cur_node->items, next) {
-                               if (cur_match != NULL &&
-                                               cur_match->type & iter->type)
-                                       goto found;
+       if (item == NULL) {
+               TAILQ_FOREACH(cur_grp, &comp->groups, next) {
+                       TAILQ_FOREACH(cur_match, &cur_grp->items, next) {
+                               if (cur_match->type & type)
+                                       return cur_match;
                        }
                }
                return NULL;
-       } else {
+       }
+
+       cur_grp = item->grp;
+       cur_match = TAILQ_NEXT(item, next);
+       while (cur_match != NULL) {
+               if (cur_match->type & type)
+                       return cur_match;
                cur_match = TAILQ_NEXT(cur_match, next);
-               if (cur_match != NULL &&
-                               cur_match->type & iter->type)
-                       goto found;
-               cur_node = TAILQ_NEXT(cur_node, next);
-               while (cur_node != NULL) {
-                       cur_match = TAILQ_FIRST(&cur_node->items);
-                       if (cur_match != NULL &&
-                                       cur_match->type & iter->type)
-                               goto found;
-                       cur_node = TAILQ_NEXT(cur_node, next);
+       }
+       cur_grp = TAILQ_NEXT(cur_grp, next);
+       while (cur_grp != NULL) {
+               TAILQ_FOREACH(cur_match, &cur_grp->items, next) {
+                       if (cur_match->type & type)
+                               return cur_match;
                }
-               return NULL;
        }
 
-found:
-       iter->cur_node = cur_node;
-       iter->cur_match = cur_match;
+       return NULL;
+}
 
-       return iter->cur_match;
+struct ec_comp_item *
+ec_comp_iter_next(struct ec_comp_item *item, enum ec_comp_type type)
+{
+       if (item == NULL)
+               return NULL;
+       return __ec_comp_iter_next(item->grp->comp, item, type);
 }
 
-void ec_comp_iter_free(struct ec_comp_iter *iter)
+
+struct ec_comp_item *
+ec_comp_iter_first(const struct ec_comp *comp, enum ec_comp_type type)
 {
-       ec_free(iter);
+       return __ec_comp_iter_next(comp, NULL, type);
 }
 
 /* LCOV_EXCL_START */
@@ -650,7 +674,6 @@ static int ec_comp_testcase(void)
 {
        struct ec_node *node = NULL;
        struct ec_comp *c = NULL;
-       struct ec_comp_iter *iter = NULL;
        struct ec_comp_item *item;
        FILE *f = NULL;
        char *buf = NULL;
@@ -664,19 +687,19 @@ static int ec_comp_testcase(void)
        if (node == NULL)
                goto fail;
 
-       c = ec_node_complete(node, "xcdscds");
+       c = ec_complete(node, "xcdscds");
        testres |= EC_TEST_CHECK(
                c != NULL && ec_comp_count(c, EC_COMP_ALL) == 0,
                "complete count should is not 0\n");
        ec_comp_free(c);
 
-       c = ec_node_complete(node, "x");
+       c = ec_complete(node, "x");
        testres |= EC_TEST_CHECK(
                c != NULL && ec_comp_count(c, EC_COMP_ALL) == 1,
                "complete count should is not 1\n");
        ec_comp_free(c);
 
-       c = ec_node_complete(node, "");
+       c = ec_complete(node, "");
        testres |= EC_TEST_CHECK(
                c != NULL && ec_comp_count(c, EC_COMP_ALL) == 2,
                "complete count should is not 2\n");
@@ -707,8 +730,7 @@ static int ec_comp_testcase(void)
        free(buf);
        buf = NULL;
 
-       iter = ec_comp_iter(c, EC_COMP_ALL);
-       item = ec_comp_iter_next(iter);
+       item = ec_comp_iter_first(c, EC_COMP_ALL);
        if (item == NULL)
                goto fail;
 
@@ -722,7 +744,7 @@ static int ec_comp_testcase(void)
                !strcmp(ec_node_id(ec_comp_item_get_node(item)), "id_x"),
                "bad item node\n");
 
-       item = ec_comp_iter_next(iter);
+       item = ec_comp_iter_next(item, EC_COMP_ALL);
        if (item == NULL)
                goto fail;
 
@@ -736,17 +758,15 @@ static int ec_comp_testcase(void)
                !strcmp(ec_node_id(ec_comp_item_get_node(item)), "id_y"),
                "bad item node\n");
 
-       item = ec_comp_iter_next(iter);
+       item = ec_comp_iter_next(item, EC_COMP_ALL);
        testres |= EC_TEST_CHECK(item == NULL, "should be the last item\n");
 
-       ec_comp_iter_free(iter);
        ec_comp_free(c);
        ec_node_free(node);
 
        return testres;
 
 fail:
-       ec_comp_iter_free(iter);
        ec_comp_free(c);
        ec_node_free(node);
        if (f != NULL)