tst.hpp 5.9 KB

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