summaryrefslogtreecommitdiff
path: root/pfxtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'pfxtree.c')
-rw-r--r--pfxtree.c100
1 files changed, 94 insertions, 6 deletions
diff --git a/pfxtree.c b/pfxtree.c
index 074bab8..c295ada 100644
--- a/pfxtree.c
+++ b/pfxtree.c
@@ -73,7 +73,8 @@ pt_deep_free(PrefixTree *self, bool free_data)
PrefixTree *child, *next = NULL;
for (child = self->children; child != NULL; child = next)
{
- if (free_data && 'p' == child->type && child->data.p != NULL)
+ if (free_data && PT_TYPE_PTR == child->type
+ && child->data.p != NULL)
free(child->data.p);
next = child->next;
@@ -110,7 +111,8 @@ get_child_by_ch(const PrefixTree *self, const int ch)
}
static int
-add(PrefixTree *self, const char *word, union _pt_data data, int type)
+add(PrefixTree *self, const char *word, union pt_data data,
+ enum pt_data_type type)
{
int rc = 0;
PrefixTree *node = self, *first_insertion = NULL;
@@ -164,17 +166,17 @@ add(PrefixTree *self, const char *word, union _pt_data data, int type)
int
pt_add(PrefixTree *self, const char *word, int data)
{
- union _pt_data d;
+ union pt_data d;
d.i = data;
- return add(self, word, d, 'i');
+ return add(self, word, d, PT_TYPE_INT);
}
int
pt_add_p(PrefixTree *self, const char *word, void *data)
{
- union _pt_data d;
+ union pt_data d;
d.p = data;
- return add(self, word, d, 'p');
+ return add(self, word, d, PT_TYPE_PTR);
}
static size_t
@@ -264,6 +266,92 @@ pt_search(const PrefixTree *root, const char *word)
return NULL;
}
+static const PrefixTree *
+delve(const PrefixTree *node, char **bufptr, size_t *bufsize, size_t *i)
+{
+ while (node->children)
+ {
+ char *buf = *bufptr;
+
+ node = node->children;
+ buf[(*i)++] = node->ch;
+ if (*i >= *bufsize)
+ {
+ char *temp;
+ *bufsize += 32;
+ temp = realloc(*bufptr, *bufsize);
+ if (!temp)
+ return NULL;
+
+ *bufptr = temp;
+ }
+ }
+
+ return node;
+}
+
+int
+pt_foreach(const PrefixTree *root, int (*f)(const struct pt_entry *,void *),
+ void *data)
+{
+ int rc = 0;
+ char *buf;
+ size_t i = 0, bufsize = 32;
+ const PrefixTree *node;
+ struct pt_entry entry;
+
+ if (!root)
+ return rc;
+
+ buf = malloc(bufsize);
+ if (!buf)
+ return PT_EALLOC;
+
+ node = delve(root, &buf, &bufsize, &i);
+ if (!node)
+ {
+ rc = PT_EALLOC;
+ goto end;
+ }
+
+ while (node->parent)
+ {
+ PrefixTree *temp;
+
+ if ('\0' == node->ch)
+ {
+ entry.word = buf;
+ entry.type = node->type;
+ entry.data = node->data;
+
+ rc = f(&entry, data);
+ if (rc)
+ goto end;
+ }
+
+ --i;
+ temp = node->next;
+ if (temp)
+ {
+ buf[i++] = temp->ch;
+ node = delve(temp, &buf, &bufsize, &i);
+ if (!node)
+ {
+ rc = PT_EALLOC;
+ goto end;
+ }
+ }
+ else
+ {
+ node = node->parent;
+ }
+ }
+
+end:
+ free(buf);
+ return rc;
+}
+
const char *
pt_version()
{