--- /dev/null
+/* ternary.h - Ternary Search Trees
+ Copyright 2001 Free Software Foundation, Inc.
+
+ Contributed by Daniel Berlin (dan@cgsoftware.com)
+
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+#ifndef TERNARY_H_
+#define TERNARY_H_
+/* Ternary search trees */
+
+typedef struct ternary_node_def *ternary_tree;
+
+typedef struct ternary_node_def
+{
+ char splitchar;
+ ternary_tree lokid;
+ ternary_tree eqkid;
+ ternary_tree hikid;
+}
+ternary_node;
+
+/* Insert string S into tree P, associating it with DATA.
+ Return the data in the tree associated with the string if it's
+ already there, and replace is 0.
+ Otherwise, replaces if it it exists, inserts if it doesn't, and
+ returns the data you passed in. */
+void *ternary_insert (ternary_tree *p, char *s, void *data, int replace);
+
+/* Delete the ternary search tree rooted at P.
+ Does NOT delete the data you associated with the strings. */
+void ternary_cleanup (ternary_tree p);
+
+/* Search the ternary tree for string S, returning the data associated
+ with it if found. */
+void *ternary_search (ternary_tree p, char *s);
+#endif
--- /dev/null
+/* ternary.c - Ternary Search Trees
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+ Contributed by Daniel Berlin (dan@cgsoftware.com)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#include "libiberty.h"
+#include "ternary.h"
+
+/* Non-recursive so we don't waste stack space/time on large
+ insertions. */
+
+void *
+ternary_insert (ternary_tree * root, char *s, void *data, int replace)
+{
+ int diff;
+ ternary_tree curr, *pcurr;
+
+ /* Start at the root. */
+ pcurr = root;
+ /* Loop until we find the right position */
+ while ((curr = *pcurr))
+ {
+ /* Calculate the difference */
+ diff = *s - curr->splitchar;
+ /* Handle current char equal to node splitchar */
+ if (diff == 0)
+ {
+ /* Handle the case of a string we already have */
+ if (*s++ == 0)
+ {
+ if (replace)
+ curr->eqkid = (ternary_tree) data;
+ return (void *) curr->eqkid;
+ }
+ pcurr = &(curr->eqkid);
+ }
+ /* Handle current char less than node splitchar */
+ else if (diff < 0)
+ {
+ pcurr = &(curr->lokid);
+ }
+ /* Handle current char greater than node splitchar */
+ else
+ {
+ pcurr = &(curr->hikid);
+ }
+ }
+ /* It's not a duplicate string, and we should insert what's left of
+ the string, into the tree rooted at curr */
+ for (;;)
+ {
+ /* Allocate the memory for the node, and fill it in */
+ *pcurr = (ternary_tree) xmalloc (sizeof (ternary_node));
+ curr = *pcurr;
+ curr->splitchar = *s;
+ curr->lokid = curr->hikid = curr->eqkid = 0;
+
+ /* Place nodes until we hit the end of the string.
+ When we hit it, place the data in the right place, and
+ return.
+ */
+ if (*s++ == 0)
+ {
+ curr->eqkid = (ternary_tree) data;
+ return data;
+ }
+ pcurr = &(curr->eqkid);
+ }
+}
+
+/* Free the ternary search tree rooted at p. */
+void
+ternary_cleanup (ternary_tree p)
+{
+ if (p)
+ {
+ ternary_cleanup (p->lokid);
+ if (p->splitchar)
+ ternary_cleanup (p->eqkid);
+ ternary_cleanup (p->hikid);
+ free (p);
+ }
+}
+
+/* Non-recursive find of a string in the ternary tree */
+void *
+ternary_search (ternary_tree p, char *s)
+{
+ ternary_tree curr;
+ int diff, spchar;
+ spchar = *s;
+ curr = p;
+ /* Loop while we haven't hit a NULL node or returned */
+ while (curr)
+ {
+ /* Calculate the difference */
+ diff = spchar - curr->splitchar;
+ /* Handle the equal case */
+ if (diff == 0)
+ {
+ if (spchar == 0)
+ return (void *) curr->eqkid;
+ spchar = *++s;
+ curr = curr->eqkid;
+ }
+ /* Handle the less than case */
+ else if (diff < 0)
+ curr = curr->lokid;
+ /* All that's left is greater than */
+ else
+ curr = curr->hikid;
+ }
+ return NULL;
+}
+
+/* For those who care, the recursive version of the search. Useful if
+ you want a starting point for pmsearch or nearsearch. */
+static void *
+ternary_recursivesearch (ternary_tree p, char *s)
+{
+ if (!p)
+ return 0;
+ if (*s < p->splitchar)
+ return ternary_recursivesearch (p->lokid, s);
+ else if (*s > p->splitchar)
+ return ternary_recursivesearch (p->hikid, s);
+ else
+ {
+ if (*s == 0)
+ return (void *) p->eqkid;
+ return ternary_recursivesearch (p->eqkid, ++s);
+ }
+}