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