tst.hpp 5.8 KB

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