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