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