• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
tst_mapboost::spirit::x3::tst_map25         tst_map()
26         {
27         }
28 
~tst_mapboost::spirit::x3::tst_map29         ~tst_map()
30         {
31             // Nothing to do here.
32             // The pools do the right thing for us
33         }
34 
tst_mapboost::spirit::x3::tst_map35         tst_map(tst_map const& rhs)
36         {
37             copy(rhs);
38         }
39 
operator =boost::spirit::x3::tst_map40         tst_map& operator=(tst_map const& rhs)
41         {
42             return assign(rhs);
43         }
44 
45         template <typename Iterator, typename Filter>
findboost::spirit::x3::tst_map46         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>
findboost::spirit::x3::tst_map68         T* find(Iterator& first, Iterator last) const
69         {
70             return find(first, last, tst_pass_through());
71         }
72 
73         template <typename Iterator>
addboost::spirit::x3::tst_map74         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>
removeboost::spirit::x3::tst_map102         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 
clearboost::spirit::x3::tst_map126         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>
for_eachboost::spirit::x3::tst_map138         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 
copyboost::spirit::x3::tst_map161         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 
assignboost::spirit::x3::tst_map172         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 
new_nodeboost::spirit::x3::tst_map186         node* new_node(Char id)
187         {
188             return node_pool.construct(id);
189         }
190 
new_databoost::spirit::x3::tst_map191         T* new_data(typename boost::call_traits<T>::param_type val)
192         {
193             return data_pool.construct(val);
194         }
195 
delete_nodeboost::spirit::x3::tst_map196         void delete_node(node* p)
197         {
198             node_pool.destroy(p);
199         }
200 
delete_databoost::spirit::x3::tst_map201         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
213