tst.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM)
  7. #define BOOST_SPIRIT_X3_TST_MARCH_09_2007_0905AM
  8. #include <boost/call_traits.hpp>
  9. #include <boost/assert.hpp>
  10. namespace boost { namespace spirit { namespace x3 { namespace detail
  11. {
  12. // This file contains low level TST routines, not for
  13. // public consumption.
  14. template <typename Char, typename T>
  15. struct tst_node
  16. {
  17. tst_node(Char id)
  18. : id(id), data(0), lt(0), eq(0), gt(0)
  19. {
  20. }
  21. template <typename Alloc>
  22. static void
  23. destruct_node(tst_node* p, Alloc* alloc)
  24. {
  25. if (p)
  26. {
  27. if (p->data)
  28. alloc->delete_data(p->data);
  29. destruct_node(p->lt, alloc);
  30. destruct_node(p->eq, alloc);
  31. destruct_node(p->gt, alloc);
  32. alloc->delete_node(p);
  33. }
  34. }
  35. template <typename Alloc>
  36. static tst_node*
  37. clone_node(tst_node* p, Alloc* alloc)
  38. {
  39. if (p)
  40. {
  41. tst_node* clone = alloc->new_node(p->id);
  42. if (p->data)
  43. clone->data = alloc->new_data(*p->data);
  44. clone->lt = clone_node(p->lt, alloc);
  45. clone->eq = clone_node(p->eq, alloc);
  46. clone->gt = clone_node(p->gt, alloc);
  47. return clone;
  48. }
  49. return 0;
  50. }
  51. template <typename Iterator, typename CaseCompare>
  52. static T*
  53. find(tst_node* start, Iterator& first, Iterator last, CaseCompare comp)
  54. {
  55. if (first == last)
  56. return 0;
  57. Iterator i = first;
  58. Iterator latest = first;
  59. tst_node* p = start;
  60. T* found = 0;
  61. while (p && i != last)
  62. {
  63. int32_t c = comp(*i,p->id);
  64. if (c == 0)
  65. {
  66. if (p->data)
  67. {
  68. found = p->data;
  69. latest = i;
  70. }
  71. p = p->eq;
  72. i++;
  73. }
  74. else if (c < 0)
  75. {
  76. p = p->lt;
  77. }
  78. else
  79. {
  80. p = p->gt;
  81. }
  82. }
  83. if (found)
  84. first = ++latest; // one past the last matching char
  85. return found;
  86. }
  87. template <typename Iterator, typename Alloc>
  88. static T*
  89. add(
  90. tst_node*& start
  91. , Iterator first
  92. , Iterator last
  93. , typename boost::call_traits<T>::param_type val
  94. , Alloc* alloc)
  95. {
  96. if (first == last)
  97. return 0;
  98. tst_node** pp = &start;
  99. for (;;)
  100. {
  101. auto c = *first;
  102. if (*pp == 0)
  103. *pp = alloc->new_node(c);
  104. tst_node* p = *pp;
  105. if (c == p->id)
  106. {
  107. if (++first == last)
  108. {
  109. if (p->data == 0)
  110. p->data = alloc->new_data(val);
  111. return p->data;
  112. }
  113. pp = &p->eq;
  114. }
  115. else if (c < p->id)
  116. {
  117. pp = &p->lt;
  118. }
  119. else
  120. {
  121. pp = &p->gt;
  122. }
  123. }
  124. }
  125. template <typename Iterator, typename Alloc>
  126. static void
  127. remove(tst_node*& p, Iterator first, Iterator last, Alloc* alloc)
  128. {
  129. if (p == 0 || first == last)
  130. return;
  131. auto c = *first;
  132. if (c == p->id)
  133. {
  134. if (++first == last)
  135. {
  136. if (p->data)
  137. {
  138. alloc->delete_data(p->data);
  139. p->data = 0;
  140. }
  141. }
  142. remove(p->eq, first, last, alloc);
  143. }
  144. else if (c < p->id)
  145. {
  146. remove(p->lt, first, last, alloc);
  147. }
  148. else
  149. {
  150. remove(p->gt, first, last, alloc);
  151. }
  152. if (p->data == 0 && p->lt == 0 && p->eq == 0 && p->gt == 0)
  153. {
  154. alloc->delete_node(p);
  155. p = 0;
  156. }
  157. }
  158. template <typename F>
  159. static void
  160. for_each(tst_node* p, std::basic_string<Char> prefix, F f)
  161. {
  162. if (p)
  163. {
  164. for_each(p->lt, prefix, f);
  165. std::basic_string<Char> s = prefix + p->id;
  166. for_each(p->eq, s, f);
  167. if (p->data)
  168. f(s, *p->data);
  169. for_each(p->gt, prefix, f);
  170. }
  171. }
  172. Char id; // the node's identity character
  173. T* data; // optional data
  174. tst_node* lt; // left pointer
  175. tst_node* eq; // middle pointer
  176. tst_node* gt; // right pointer
  177. };
  178. }}}}
  179. #endif