ttree.hh 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. //{{{ Ternary Tree
  9. //
  10. // Maps strings into user definable data (e.g. symbol tables) using the ternary tree
  11. // method, a combination of binary tree and trie. To use, either use the
  12. // i4_base_ternary_tree class or instatiate a template class from the template
  13. // i4_ternary_tree. the template just performs casting, so should produce minimal code,
  14. // but improves static type-checking. in either case, the data stored should be
  15. // castable to and from a 'void*'. larger structures should be allocated and then the
  16. // pointer to the structure can be stored in the tree.
  17. //
  18. // i4_base_ternary_tree tree; // tree of string/void* pairs
  19. // i4_ternary_tree<CMyData *> tree; // tree of string/MyData* pairs
  20. //
  21. // To add key/value pairs:
  22. //
  23. // CMyData *value;
  24. // tree.add("token", value);
  25. // // add a single key/value pair, return i4_F if no collisions found
  26. // // if there was a collision, replace the value for the key, and return i4_T
  27. //
  28. // CMyData *value, *old_value;
  29. // tree.add("token", value, &old_value);
  30. // // add a key/value pair, returns i4_F if no collisions found
  31. // // if there was a collision, replace the value, store the old value, and return i4_T
  32. //
  33. // To search for and retrieve key/value pairs:
  34. //
  35. // i4_bool found = tree.find("token");
  36. // // searches for the key, returns whether the key was found
  37. //
  38. // CMyData *value;
  39. // i4_bool found = tree.find("token", &value);
  40. // // searches for the key, stores value and returns i4_T on success, i4_F otherwise
  41. //
  42. // To remove key/value pairs
  43. //
  44. // tree.remove("token");
  45. // // removes the key/value from the tree, returns i4_T on success, i4_F if not found
  46. //
  47. // CMyData *old_value;
  48. // tree.remove("token", &old_value);
  49. // // removes the key/value from the tree, stores old value and returns i4_T on success
  50. //
  51. // To iterate through the key/value pairs,
  52. //
  53. // char key_buffer[1024];
  54. // i4_base_ternary_tree::iterator i(tree, key_buffer, sizeof(key_buffer));
  55. // // for string/void* iterator
  56. // i4_ternary_tree<CMyData *>::iterator i(tree, key_buffer, sizeof(key_buffer));
  57. // // for typed iterator for CMyData*
  58. //
  59. // for (; !i.end(); i++) // iterate through the tree, alphabetically
  60. // {
  61. // char *key = i.key(); // get the current string key (returns the original key_buffer)
  62. // // and gets destroyed upon the next iteration
  63. //
  64. // CMyData *value = *i; // if i is a iterator of the templatized type
  65. // CMyData *value = *i.get();
  66. //
  67. // void *value = i.get(); // if i is a iterator of the base ternary tree
  68. //
  69. // i++; // various ways to iterate to the next key/value pair
  70. // ++i;
  71. // i.next();
  72. // }
  73. //
  74. //
  75. // $Id: ttree.hh,v 1.3 1998/06/17 18:05:28 oliy Exp $
  76. //}}}
  77. #ifndef TTREE_HH
  78. #define TTREE_HH
  79. #include "memory/lalloc.hh"
  80. #include "memory/array.hh"
  81. typedef char CHAR;
  82. class i4_base_ternary_tree
  83. {
  84. protected:
  85. class node
  86. //{{{
  87. {
  88. public:
  89. CHAR ch;
  90. node *lo, *eq, *hi;
  91. void* data() const { return (void*)eq; }
  92. void set_data(void *new_data) { eq = (node*)new_data; }
  93. };
  94. //}}}
  95. i4_linear_allocator_template<node> heap;
  96. node *root;
  97. i4_bool unlink(node **n, const CHAR *s, void **old_data=0);
  98. node *find_node(const CHAR *s) const;
  99. public:
  100. class iterator
  101. //{{{
  102. {
  103. protected:
  104. i4_array<node *> node_stack;
  105. i4_array<int> index_stack;
  106. node *current;
  107. CHAR *buff;
  108. int pos, maxlen;
  109. void push(node *n)
  110. //{{{
  111. {
  112. if (!n)
  113. return;
  114. node_stack.add(n);
  115. index_stack.add(0);
  116. }
  117. //}}}
  118. void pop()
  119. //{{{
  120. {
  121. node_stack.remove(node_stack.size()-1);
  122. index_stack.remove(index_stack.size()-1);
  123. }
  124. //}}}
  125. public:
  126. iterator(const i4_base_ternary_tree &tree, CHAR *buff, int maxlen)
  127. : node_stack(40, 40), index_stack(40,40), buff(buff), current(0), pos(0), maxlen(maxlen)
  128. //{{{
  129. {
  130. // reserve last character for terminator
  131. maxlen--;
  132. buff[maxlen]=0;
  133. // start from the root and iterate
  134. push(tree.root);
  135. next();
  136. }
  137. //}}}
  138. i4_bool end() const { return node_stack.size()==0; }
  139. const CHAR *key() const { return buff; }
  140. void *get() const { return current->data(); }
  141. void next();
  142. iterator& operator++() { next(); return *this; }
  143. iterator& operator++(int) { next(); return *this; }
  144. };
  145. //}}}
  146. friend class i4_base_ternary_tree::iterator;
  147. i4_base_ternary_tree() : root(0), heap(1024,1024,"ternary tree heap") {}
  148. i4_bool add(const CHAR *s, void *new_data, i4_bool replace=i4_T, void**old_data=0);
  149. i4_bool remove(const CHAR *s, void **old_data=0) { return unlink(&root, s, old_data); }
  150. i4_bool find(const CHAR *s, void **data=0) const
  151. //{{{
  152. {
  153. node *n = find_node(s);
  154. if (n && data)
  155. *data = n->data();
  156. return n!=0;
  157. }
  158. //}}}
  159. };
  160. template<class T>
  161. class i4_ternary_tree : public i4_base_ternary_tree
  162. {
  163. public:
  164. class iterator : public i4_base_ternary_tree::iterator
  165. {
  166. public:
  167. iterator(const i4_ternary_tree &tree, CHAR *buff, int maxlen)
  168. : i4_base_ternary_tree::iterator(tree,buff,maxlen) {}
  169. T get() const { return (T)i4_base_ternary_tree::iterator::get(); }
  170. T operator*() const { return get(); }
  171. };
  172. i4_bool add(CHAR *s, T new_data, i4_bool replace=i4_T, T* old_data=0)
  173. { return i4_base_ternary_tree::add(s, (void*)new_data, replace, (void**)old_data); }
  174. i4_bool remove(CHAR *s, T* old_data=0)
  175. { return i4_base_ternary_tree::remove(s, (void**)old_data); }
  176. i4_bool find(CHAR *s, T* old_data=0) const
  177. { return i4_base_ternary_tree::find(s, (void**)old_data); }
  178. };
  179. #endif
  180. //{{{ Emacs Locals
  181. // Local Variables:
  182. // folded-file: t
  183. // End:
  184. //}}}