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