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_MAP_JUNE_03_2007_1143AM)
|
Chris@16
|
8 #define BOOST_SPIRIT_TST_MAP_JUNE_03_2007_1143AM
|
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/spirit/home/qi/string/detail/tst.hpp>
|
Chris@16
|
15 #include <boost/unordered_map.hpp>
|
Chris@16
|
16 #include <boost/pool/object_pool.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 namespace boost { namespace spirit { namespace qi
|
Chris@16
|
19 {
|
Chris@16
|
20 struct tst_pass_through; // declared in tst.hpp
|
Chris@16
|
21
|
Chris@16
|
22 template <typename Char, typename T>
|
Chris@16
|
23 struct tst_map
|
Chris@16
|
24 {
|
Chris@16
|
25 typedef Char char_type; // the character type
|
Chris@16
|
26 typedef T value_type; // the value associated with each entry
|
Chris@16
|
27 typedef detail::tst_node<Char, T> node;
|
Chris@16
|
28
|
Chris@16
|
29 tst_map()
|
Chris@16
|
30 {
|
Chris@16
|
31 }
|
Chris@16
|
32
|
Chris@16
|
33 ~tst_map()
|
Chris@16
|
34 {
|
Chris@16
|
35 // Nothing to do here.
|
Chris@16
|
36 // The pools do the right thing for us
|
Chris@16
|
37 }
|
Chris@16
|
38
|
Chris@16
|
39 tst_map(tst_map const& rhs)
|
Chris@16
|
40 {
|
Chris@16
|
41 copy(rhs);
|
Chris@16
|
42 }
|
Chris@16
|
43
|
Chris@16
|
44 tst_map& operator=(tst_map const& rhs)
|
Chris@16
|
45 {
|
Chris@16
|
46 return assign(rhs);
|
Chris@16
|
47 }
|
Chris@16
|
48
|
Chris@16
|
49 template <typename Iterator, typename Filter>
|
Chris@16
|
50 T* find(Iterator& first, Iterator last, Filter filter) const
|
Chris@16
|
51 {
|
Chris@16
|
52 if (first != last)
|
Chris@16
|
53 {
|
Chris@16
|
54 Iterator save = first;
|
Chris@16
|
55 typename map_type::const_iterator
|
Chris@16
|
56 i = map.find(filter(*first++));
|
Chris@101
|
57
|
Chris@101
|
58 if (i != map.end())
|
Chris@16
|
59 {
|
Chris@101
|
60 if (T* p = node::find(i->second.root, first, last, filter))
|
Chris@101
|
61 {
|
Chris@101
|
62 return p;
|
Chris@101
|
63 }
|
Chris@101
|
64
|
Chris@101
|
65 if (i->second.data)
|
Chris@101
|
66 {
|
Chris@101
|
67 return i->second.data;
|
Chris@101
|
68 }
|
Chris@16
|
69 }
|
Chris@101
|
70 first = save;
|
Chris@16
|
71 }
|
Chris@16
|
72 return 0;
|
Chris@16
|
73 }
|
Chris@16
|
74
|
Chris@16
|
75 template <typename Iterator>
|
Chris@16
|
76 T* find(Iterator& first, Iterator last) const
|
Chris@16
|
77 {
|
Chris@16
|
78 return find(first, last, tst_pass_through());
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 template <typename Iterator>
|
Chris@16
|
82 bool add(
|
Chris@16
|
83 Iterator first
|
Chris@16
|
84 , Iterator last
|
Chris@16
|
85 , typename boost::call_traits<T>::param_type val)
|
Chris@16
|
86 {
|
Chris@16
|
87 if (first != last)
|
Chris@16
|
88 {
|
Chris@16
|
89 map_data x = {0, 0};
|
Chris@16
|
90 std::pair<typename map_type::iterator, bool>
|
Chris@16
|
91 r = map.insert(std::pair<Char, map_data>(*first++, x));
|
Chris@16
|
92
|
Chris@16
|
93 if (first != last)
|
Chris@16
|
94 {
|
Chris@16
|
95 return node::add(r.first->second.root
|
Chris@16
|
96 , first, last, val, this) ? true : false;
|
Chris@16
|
97 }
|
Chris@16
|
98 else
|
Chris@16
|
99 {
|
Chris@16
|
100 if (r.first->second.data)
|
Chris@16
|
101 return false;
|
Chris@16
|
102 r.first->second.data = this->new_data(val);
|
Chris@16
|
103 }
|
Chris@16
|
104 return true;
|
Chris@16
|
105 }
|
Chris@16
|
106 return false;
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 template <typename Iterator>
|
Chris@16
|
110 void remove(Iterator first, Iterator last)
|
Chris@16
|
111 {
|
Chris@16
|
112 if (first != last)
|
Chris@16
|
113 {
|
Chris@16
|
114 typename map_type::iterator i = map.find(*first++);
|
Chris@16
|
115 if (i != map.end())
|
Chris@16
|
116 {
|
Chris@16
|
117 if (first != last)
|
Chris@16
|
118 {
|
Chris@16
|
119 node::remove(i->second.root, first, last, this);
|
Chris@16
|
120 }
|
Chris@16
|
121 else if (i->second.data)
|
Chris@16
|
122 {
|
Chris@16
|
123 this->delete_data(i->second.data);
|
Chris@16
|
124 i->second.data = 0;
|
Chris@16
|
125 }
|
Chris@16
|
126 if (i->second.data == 0 && i->second.root == 0)
|
Chris@16
|
127 {
|
Chris@16
|
128 map.erase(i);
|
Chris@16
|
129 }
|
Chris@16
|
130 }
|
Chris@16
|
131 }
|
Chris@16
|
132 }
|
Chris@16
|
133
|
Chris@16
|
134 void clear()
|
Chris@16
|
135 {
|
Chris@16
|
136 BOOST_FOREACH(typename map_type::value_type& x, map)
|
Chris@16
|
137 {
|
Chris@16
|
138 node::destruct_node(x.second.root, this);
|
Chris@16
|
139 if (x.second.data)
|
Chris@16
|
140 this->delete_data(x.second.data);
|
Chris@16
|
141 }
|
Chris@16
|
142 map.clear();
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 template <typename F>
|
Chris@16
|
146 void for_each(F f) const
|
Chris@16
|
147 {
|
Chris@16
|
148 BOOST_FOREACH(typename map_type::value_type const& x, map)
|
Chris@16
|
149 {
|
Chris@16
|
150 std::basic_string<Char> s(1, x.first);
|
Chris@16
|
151 node::for_each(x.second.root, s, f);
|
Chris@16
|
152 if (x.second.data)
|
Chris@16
|
153 f(s, *x.second.data);
|
Chris@16
|
154 }
|
Chris@16
|
155 }
|
Chris@16
|
156
|
Chris@16
|
157 private:
|
Chris@16
|
158
|
Chris@16
|
159 friend struct detail::tst_node<Char, T>;
|
Chris@16
|
160
|
Chris@16
|
161 struct map_data
|
Chris@16
|
162 {
|
Chris@16
|
163 node* root;
|
Chris@16
|
164 T* data;
|
Chris@16
|
165 };
|
Chris@16
|
166
|
Chris@16
|
167 typedef unordered_map<Char, map_data> map_type;
|
Chris@16
|
168
|
Chris@16
|
169 void copy(tst_map const& rhs)
|
Chris@16
|
170 {
|
Chris@16
|
171 BOOST_FOREACH(typename map_type::value_type const& x, rhs.map)
|
Chris@16
|
172 {
|
Chris@16
|
173 map_data xx = {node::clone_node(x.second.root, this), 0};
|
Chris@16
|
174 if (x.second.data)
|
Chris@16
|
175 xx.data = data_pool.construct(*x.second.data);
|
Chris@16
|
176 map[x.first] = xx;
|
Chris@16
|
177 }
|
Chris@16
|
178 }
|
Chris@16
|
179
|
Chris@16
|
180 tst_map& assign(tst_map const& rhs)
|
Chris@16
|
181 {
|
Chris@16
|
182 if (this != &rhs)
|
Chris@16
|
183 {
|
Chris@16
|
184 BOOST_FOREACH(typename map_type::value_type& x, map)
|
Chris@16
|
185 {
|
Chris@16
|
186 node::destruct_node(x.second.root, this);
|
Chris@16
|
187 }
|
Chris@16
|
188 map.clear();
|
Chris@16
|
189 copy(rhs);
|
Chris@16
|
190 }
|
Chris@16
|
191 return *this;
|
Chris@16
|
192 }
|
Chris@16
|
193
|
Chris@16
|
194 node* new_node(Char id)
|
Chris@16
|
195 {
|
Chris@16
|
196 return node_pool.construct(id);
|
Chris@16
|
197 }
|
Chris@16
|
198
|
Chris@16
|
199 T* new_data(typename boost::call_traits<T>::param_type val)
|
Chris@16
|
200 {
|
Chris@16
|
201 return data_pool.construct(val);
|
Chris@16
|
202 }
|
Chris@16
|
203
|
Chris@16
|
204 void delete_node(node* p)
|
Chris@16
|
205 {
|
Chris@16
|
206 node_pool.destroy(p);
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 void delete_data(T* p)
|
Chris@16
|
210 {
|
Chris@16
|
211 data_pool.destroy(p);
|
Chris@16
|
212 }
|
Chris@16
|
213
|
Chris@16
|
214 map_type map;
|
Chris@16
|
215 object_pool<node> node_pool;
|
Chris@16
|
216 object_pool<T> data_pool;
|
Chris@16
|
217 };
|
Chris@16
|
218 }}}
|
Chris@16
|
219
|
Chris@16
|
220 #endif
|