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