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