Gera critério de obrigatoriedade.
[cascardo/declara.git] / list.c
diff --git a/list.c b/list.c
index 00b9f7c..87913c4 100644 (file)
--- a/list.c
+++ b/list.c
@@ -43,6 +43,23 @@ struct list * list_new(void)
        return list;
 }
 
+static struct list * list_expand(struct list **list)
+{
+       struct list *l = *list;
+       struct list *nlist;
+       size_t len = l->alen * sizeof(struct item);
+       size_t nlen = len * 2;
+       nlist = realloc(l, sizeof(*nlist) + nlen);
+       if (!nlist)
+               goto out;
+       *list = l = nlist;
+       memset(&l->items[l->len], 0, len);
+       l->alen = l->alen * 2;
+       return l;
+out:
+       return NULL;
+}
+
 int list_add(struct list **list, void *val)
 {
        unsigned int i;
@@ -50,15 +67,9 @@ int list_add(struct list **list, void *val)
        l->items[l->len].val = val;
        l->len++;
        if (l->len == l->alen) {
-               struct list *nlist;
-               size_t len = l->alen * sizeof(struct item);
-               size_t nlen = len * 2;
-               nlist = realloc(l, sizeof(*nlist) + nlen);
-               if (!nlist)
+               l = list_expand(list);
+               if (!l)
                        goto out;
-               *list = l = nlist;
-               memset(&l->items[l->len], 0, len);
-               l->alen = l->alen * 2;
        }
        return 0;
 out:
@@ -66,6 +77,36 @@ out:
        return -1;
 }
 
+int list_insert(struct list **list, int pos, void *val)
+{
+       struct list *l = *list;
+       if (pos > l->len)
+               return -1;
+       if (l->len + 1 == l->alen) {
+               l = list_expand(list);
+               if (!l)
+                       goto out;
+       }
+       if (pos < l->len)
+               memmove(&l->items[pos + 1], &l->items[pos],
+                       (l->len - pos) * sizeof(struct item));
+       l->items[pos].val = val;
+       l->len++;
+       return 0;
+out:
+       return -1;
+}
+
+int list_insert_ordered(struct list **list, void *val, sort_function_t *fn)
+{
+       struct list *l = *list;
+       int i;
+       for (i = 0; i < l->len; i++)
+               if (fn(l->items[i].val, val) >= 0)
+                       return list_insert(list, i, val);
+       return list_add(list, val);
+}
+
 void * list_get(struct list *list, int pos)
 {
        unsigned int i;