• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <boost/foreach.hpp>
19 
20 namespace boost { namespace spirit { namespace qi
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 
tst_mapboost::spirit::qi::tst_map29         tst_map()
30         {
31         }
32 
~tst_mapboost::spirit::qi::tst_map33         ~tst_map()
34         {
35             // Nothing to do here.
36             // The pools do the right thing for us
37         }
38 
tst_mapboost::spirit::qi::tst_map39         tst_map(tst_map const& rhs)
40         {
41             copy(rhs);
42         }
43 
operator =boost::spirit::qi::tst_map44         tst_map& operator=(tst_map const& rhs)
45         {
46             return assign(rhs);
47         }
48 
49         template <typename Iterator, typename Filter>
findboost::spirit::qi::tst_map50         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 
58                 if (i != map.end())
59                 {
60                     if (T* p = node::find(i->second.root, first, last, filter))
61                     {
62                         return p;
63                     }
64 
65                     if (i->second.data)
66                     {
67                         return i->second.data;
68                     }
69                 }
70                 first = save;
71             }
72             return 0;
73         }
74 
75         template <typename Iterator>
findboost::spirit::qi::tst_map76         T* find(Iterator& first, Iterator last) const
77         {
78             return find(first, last, tst_pass_through());
79         }
80 
81         template <typename Iterator>
addboost::spirit::qi::tst_map82         bool add(
83             Iterator first
84           , Iterator last
85           , typename boost::call_traits<T>::param_type val)
86         {
87             if (first != last)
88             {
89                 map_data x = {0, 0};
90                 std::pair<typename map_type::iterator, bool>
91                     r = map.insert(std::pair<Char, map_data>(*first++, x));
92 
93                 if (first != last)
94                 {
95                     return node::add(r.first->second.root
96                       , first, last, val, this) ? true : false;
97                 }
98                 else
99                 {
100                     if (r.first->second.data)
101                         return false;
102                     r.first->second.data = this->new_data(val);
103                 }
104                 return true;
105             }
106             return false;
107         }
108 
109         template <typename Iterator>
removeboost::spirit::qi::tst_map110         void remove(Iterator first, Iterator last)
111         {
112             if (first != last)
113             {
114                 typename map_type::iterator i = map.find(*first++);
115                 if (i != map.end())
116                 {
117                     if (first != last)
118                     {
119                         node::remove(i->second.root, first, last, this);
120                     }
121                     else if (i->second.data)
122                     {
123                         this->delete_data(i->second.data);
124                         i->second.data = 0;
125                     }
126                     if (i->second.data == 0 && i->second.root == 0)
127                     {
128                         map.erase(i);
129                     }
130                 }
131             }
132         }
133 
clearboost::spirit::qi::tst_map134         void clear()
135         {
136             BOOST_FOREACH(typename map_type::value_type& x, map)
137             {
138                 node::destruct_node(x.second.root, this);
139                 if (x.second.data)
140                     this->delete_data(x.second.data);
141             }
142             map.clear();
143         }
144 
145         template <typename F>
for_eachboost::spirit::qi::tst_map146         void for_each(F f) const
147         {
148             BOOST_FOREACH(typename map_type::value_type const& x, map)
149             {
150                 std::basic_string<Char> s(1, x.first);
151                 node::for_each(x.second.root, s, f);
152                 if (x.second.data)
153                     f(s, *x.second.data);
154             }
155         }
156 
157     private:
158 
159         friend struct detail::tst_node<Char, T>;
160 
161         struct map_data
162         {
163             node* root;
164             T* data;
165         };
166 
167         typedef unordered_map<Char, map_data> map_type;
168 
copyboost::spirit::qi::tst_map169         void copy(tst_map const& rhs)
170         {
171             BOOST_FOREACH(typename map_type::value_type const& x, rhs.map)
172             {
173                 map_data xx = {node::clone_node(x.second.root, this), 0};
174                 if (x.second.data)
175                     xx.data = data_pool.construct(*x.second.data);
176                 map[x.first] = xx;
177             }
178         }
179 
assignboost::spirit::qi::tst_map180         tst_map& assign(tst_map const& rhs)
181         {
182             if (this != &rhs)
183             {
184                 BOOST_FOREACH(typename map_type::value_type& x, map)
185                 {
186                     node::destruct_node(x.second.root, this);
187                 }
188                 map.clear();
189                 copy(rhs);
190             }
191             return *this;
192         }
193 
new_nodeboost::spirit::qi::tst_map194         node* new_node(Char id)
195         {
196             return node_pool.construct(id);
197         }
198 
new_databoost::spirit::qi::tst_map199         T* new_data(typename boost::call_traits<T>::param_type val)
200         {
201             return data_pool.construct(val);
202         }
203 
delete_nodeboost::spirit::qi::tst_map204         void delete_node(node* p)
205         {
206             node_pool.destroy(p);
207         }
208 
delete_databoost::spirit::qi::tst_map209         void delete_data(T* p)
210         {
211             data_pool.destroy(p);
212         }
213 
214         map_type map;
215         object_pool<node> node_pool;
216         object_pool<T> data_pool;
217     };
218 }}}
219 
220 #endif
221