source: golgotha/src/i4/inc/ttree.hh

Last change on this file was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 6.4 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9//{{{ Ternary Tree
10// 
11//  Maps strings into user definable data (e.g. symbol tables) using the ternary tree
12//  method, a combination of binary tree and trie.  To use, either use the
13//  i4_base_ternary_tree class or instatiate a template class from the template
14//  i4_ternary_tree.  the template just performs casting, so should produce minimal code,
15//  but improves static type-checking.  in either case, the data stored should be
16//  castable to and from a 'void*'.  larger structures should be allocated and then the
17//  pointer to the structure can be stored in the tree.
18//
19//    i4_base_ternary_tree tree;            // tree of string/void* pairs
20//    i4_ternary_tree<CMyData *> tree;      // tree of string/MyData* pairs
21//
22//  To add key/value pairs:
23//   
24//    CMyData *value;
25//    tree.add("token", value);
26//    //  add a single key/value pair, return i4_F if no collisions found
27//    //  if there was a collision, replace the value for the key, and return i4_T
28// 
29//    CMyData *value, *old_value;
30//    tree.add("token", value, &old_value);
31//    //  add a key/value pair, returns i4_F if no collisions found
32//    //  if there was a collision, replace the value, store the old value, and return i4_T
33//
34//  To search for and retrieve key/value pairs:
35//
36//    i4_bool found = tree.find("token");
37//    //  searches for the key, returns whether the key was found
38//
39//    CMyData *value;
40//    i4_bool found = tree.find("token", &value);
41//    //  searches for the key, stores value and returns i4_T on success, i4_F otherwise
42//
43//  To remove key/value pairs
44//
45//    tree.remove("token");
46//    //  removes the key/value from the tree, returns i4_T on success, i4_F if not found
47// 
48//    CMyData *old_value;
49//    tree.remove("token", &old_value);
50//    //  removes the key/value from the tree, stores old value and returns i4_T on success
51// 
52//  To iterate through the key/value pairs,
53//
54//    char key_buffer[1024];
55//    i4_base_ternary_tree::iterator i(tree, key_buffer, sizeof(key_buffer));
56//    //  for string/void* iterator
57//    i4_ternary_tree<CMyData *>::iterator i(tree, key_buffer, sizeof(key_buffer));
58//    //  for typed iterator for CMyData*
59//
60//    for (; !i.end(); i++)      // iterate through the tree, alphabetically
61//    {
62//      char *key = i.key();     // get the current string key (returns the original key_buffer)
63//                               // and gets destroyed upon the next iteration
64//
65//      CMyData *value = *i;     // if i is a iterator of the templatized type
66//      CMyData *value = *i.get();
67//
68//      void *value = i.get();   // if i is a iterator of the base ternary tree
69//
70//      i++;                     // various ways to iterate to the next key/value pair
71//      ++i;
72//      i.next();
73//    }
74//
75//   
76//  $Id: ttree.hh,v 1.3 1998/06/17 18:05:28 oliy Exp $
77//}}}
78
79#ifndef TTREE_HH
80#define TTREE_HH
81
82#include "memory/lalloc.hh"
83#include "memory/array.hh"
84
85typedef char CHAR;
86
87class i4_base_ternary_tree
88{
89protected:
90  class node
91  //{{{
92  {
93  public:
94    CHAR ch;
95    node *lo, *eq, *hi;
96   
97    void* data() const { return (void*)eq; }
98    void set_data(void *new_data) { eq = (node*)new_data; }
99  };
100  //}}}
101  i4_linear_allocator_template<node> heap;
102  node *root;
103
104  i4_bool unlink(node **n, const CHAR *s, void **old_data=0);
105  node *find_node(const CHAR *s) const;
106public:
107  class iterator
108  //{{{
109  {
110  protected:
111    i4_array<node *> node_stack;
112    i4_array<int>    index_stack;
113
114    node *current;
115    CHAR *buff;
116    int pos, maxlen;
117
118    void push(node *n)
119    //{{{
120    {
121      if (!n)
122        return;
123
124      node_stack.add(n);
125      index_stack.add(0);
126    }
127    //}}}
128
129    void pop()
130    //{{{
131    {
132      node_stack.remove(node_stack.size()-1);
133      index_stack.remove(index_stack.size()-1);
134    }
135    //}}}
136  public:
137    iterator(const i4_base_ternary_tree &tree, CHAR *buff, int maxlen)
138      : node_stack(40, 40), index_stack(40,40), buff(buff), current(0), pos(0), maxlen(maxlen)
139    //{{{
140    {
141      // reserve last character for terminator
142      maxlen--;
143      buff[maxlen]=0;
144
145      // start from the root and iterate
146      push(tree.root);
147      next();
148    }
149    //}}}
150
151    i4_bool end() const { return node_stack.size()==0; }
152
153    const CHAR *key() const { return buff; }
154    void *get() const { return current->data(); }
155
156    void next();
157   
158    iterator& operator++()    { next(); return *this; }
159    iterator& operator++(int) { next(); return *this; }
160  };
161  //}}}
162  friend class i4_base_ternary_tree::iterator;
163
164  i4_base_ternary_tree() : root(0), heap(1024,1024,"ternary tree heap") {}
165
166  i4_bool add(const CHAR *s, void *new_data, i4_bool replace=i4_T, void**old_data=0);
167  i4_bool remove(const CHAR *s, void **old_data=0) { return unlink(&root, s, old_data); }
168  i4_bool find(const CHAR *s, void **data=0) const
169  //{{{
170  {
171    node *n = find_node(s);
172
173    if (n && data)
174      *data = n->data();
175     
176    return n!=0;
177  }
178  //}}}
179};
180
181template<class T>
182class i4_ternary_tree : public i4_base_ternary_tree
183{
184public:
185  class iterator : public i4_base_ternary_tree::iterator
186  {
187  public:
188    iterator(const i4_ternary_tree &tree, CHAR *buff, int maxlen)
189      : i4_base_ternary_tree::iterator(tree,buff,maxlen) {}
190
191    T get() const { return (T)i4_base_ternary_tree::iterator::get(); }
192    T operator*() const { return get(); }
193  };
194
195  i4_bool add(CHAR *s, T new_data, i4_bool replace=i4_T, T* old_data=0)
196  { return i4_base_ternary_tree::add(s, (void*)new_data, replace, (void**)old_data); }
197  i4_bool remove(CHAR *s, T* old_data=0)
198  { return i4_base_ternary_tree::remove(s, (void**)old_data); }
199  i4_bool find(CHAR *s, T* old_data=0) const
200  { return i4_base_ternary_tree::find(s, (void**)old_data); }
201};
202
203#endif
204
205//{{{ Emacs Locals
206// Local Variables:
207// folded-file: t
208// End:
209//}}}
Note: See TracBrowser for help on using the repository browser.