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