ttree.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. #include "ttree.hh"
  9. void i4_base_ternary_tree::iterator::next()
  10. //{{{
  11. {
  12. current=0;
  13. while (!current)
  14. {
  15. if (end())
  16. return;
  17. // get current stack context
  18. node *n = node_stack[node_stack.size()-1];
  19. int i = index_stack[index_stack.size()-1]++;
  20. switch(i)
  21. {
  22. case 0:
  23. // traverse lo branch
  24. push(n->lo);
  25. break;
  26. case 1:
  27. // add character to current word
  28. if (pos<maxlen) buff[pos] = n->ch;
  29. pos++;
  30. if (n->ch)
  31. // traverse remaining word
  32. push(n->eq);
  33. else
  34. // found next valid word
  35. current = n;
  36. break;
  37. case 2:
  38. // remove character
  39. pos--;
  40. // traverse hi branch;
  41. push(n->hi);
  42. break;
  43. case 3:
  44. // go up stack
  45. pop();
  46. break;
  47. }
  48. }
  49. }
  50. //}}}
  51. i4_bool i4_base_ternary_tree::unlink(node **o, const CHAR *s, void **old_data)
  52. //{{{
  53. // recursively traverses the tree to remove a key/value pair
  54. {
  55. node *n = *o;
  56. if (!n)
  57. return 0;
  58. i4_bool ret;
  59. i4_bool found=i4_F;
  60. if (*s < n->ch)
  61. ret = unlink(&n->lo, s, old_data);
  62. else if (*s > n->ch)
  63. ret = unlink(&n->hi, s, old_data);
  64. else if (*s)
  65. ret = unlink(&n->eq, s+1, old_data);
  66. else
  67. {
  68. ret = found = i4_T;
  69. // store old data
  70. if (old_data) *old_data = n->data();
  71. }
  72. if (found || !n->eq)
  73. {
  74. // node is either the terminator to be removed, or a node that now has no continuation,
  75. // so we should delete it, like deleting out of a binary tree
  76. if (!n->lo && !n->hi)
  77. // no children, just axe me
  78. *o=0;
  79. else if (!n->lo || !n->hi)
  80. // one child, just bump child up
  81. *o = n->lo? n->lo : n->hi;
  82. else
  83. {
  84. // two children, find succesor to replace me
  85. // find the successor
  86. node **psplice, *splice;
  87. psplice = &n->hi;
  88. while ((splice = *psplice)->lo)
  89. psplice = &splice->lo;
  90. // unlink successor from its parent
  91. *psplice = splice->hi;
  92. // splice successor in
  93. splice->lo = n->lo;
  94. splice->hi = n->hi;
  95. *o = splice;
  96. }
  97. heap.free(n);
  98. }
  99. return ret;
  100. }
  101. //}}}
  102. i4_base_ternary_tree::node *i4_base_ternary_tree::find_node(const CHAR *s) const
  103. //{{{
  104. {
  105. node *n=root;
  106. while (n)
  107. {
  108. if (*s < n->ch) n = n->lo;
  109. else if (*s > n->ch) n = n->hi;
  110. else if (*s) { n = n->eq; s++; }
  111. else return n;
  112. }
  113. return 0;
  114. }
  115. //}}}
  116. i4_bool i4_base_ternary_tree::add(const CHAR *s, void *new_data, i4_bool replace, void **old_data)
  117. //{{{
  118. {
  119. i4_bool collide = i4_T;
  120. node **p=&root, *n;
  121. while (1)
  122. {
  123. n = *p;
  124. if (!n)
  125. {
  126. // create new node
  127. n = heap.alloc();
  128. n->ch = *s;
  129. n->lo = n->hi = n->eq = 0;
  130. collide = i4_F;
  131. *p = n;
  132. }
  133. if (*s < n->ch) p = &n->lo;
  134. else if (*s > n->ch) p = &n->hi;
  135. else if (*s) { p = &n->eq; s++; }
  136. else
  137. {
  138. if (old_data)
  139. *old_data = n->data(); // store old data
  140. if (!collide || replace)
  141. n->set_data(new_data); // store new data
  142. return collide;
  143. }
  144. }
  145. }
  146. //}}}
  147. //{{{ Emacs Locals
  148. // Local Variables:
  149. // folded-file: t
  150. // End:
  151. //}}}