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