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