| /*============================================================================= |
| Copyright (c) 2001-2010 Joel de Guzman |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| ==============================================================================*/ |
| #if !defined(BOOST_SPIRIT_TST_MAP_JUNE_03_2007_1143AM) |
| #define BOOST_SPIRIT_TST_MAP_JUNE_03_2007_1143AM |
| |
| #if defined(_MSC_VER) |
| #pragma once |
| #endif |
| |
| #include <boost/spirit/home/qi/string/detail/tst.hpp> |
| #include <boost/unordered_map.hpp> |
| #include <boost/pool/object_pool.hpp> |
| |
| namespace boost { namespace spirit { namespace qi |
| { |
| struct tst_pass_through; // declared in tst.hpp |
| |
| template <typename Char, typename T> |
| struct tst_map |
| { |
| typedef Char char_type; // the character type |
| typedef T value_type; // the value associated with each entry |
| typedef detail::tst_node<Char, T> node; |
| |
| tst_map() |
| { |
| } |
| |
| ~tst_map() |
| { |
| // Nothing to do here. |
| // The pools do the right thing for us |
| } |
| |
| tst_map(tst_map const& rhs) |
| { |
| copy(rhs); |
| } |
| |
| tst_map& operator=(tst_map const& rhs) |
| { |
| return assign(rhs); |
| } |
| |
| template <typename Iterator, typename Filter> |
| T* find(Iterator& first, Iterator last, Filter filter) const |
| { |
| if (first != last) |
| { |
| Iterator save = first; |
| typename map_type::const_iterator |
| i = map.find(filter(*first++)); |
| if (i == map.end()) |
| { |
| first = save; |
| return 0; |
| } |
| if (T* p = node::find(i->second.root, first, last, filter)) |
| { |
| return p; |
| } |
| return i->second.data; |
| } |
| return 0; |
| } |
| |
| template <typename Iterator> |
| T* find(Iterator& first, Iterator last) const |
| { |
| return find(first, last, tst_pass_through()); |
| } |
| |
| template <typename Iterator> |
| bool add( |
| Iterator first |
| , Iterator last |
| , typename boost::call_traits<T>::param_type val) |
| { |
| if (first != last) |
| { |
| map_data x = {0, 0}; |
| std::pair<typename map_type::iterator, bool> |
| r = map.insert(std::pair<Char, map_data>(*first++, x)); |
| |
| if (first != last) |
| { |
| return node::add(r.first->second.root |
| , first, last, val, this) ? true : false; |
| } |
| else |
| { |
| if (r.first->second.data) |
| return false; |
| r.first->second.data = this->new_data(val); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| template <typename Iterator> |
| void remove(Iterator first, Iterator last) |
| { |
| if (first != last) |
| { |
| typename map_type::iterator i = map.find(*first++); |
| if (i != map.end()) |
| { |
| if (first != last) |
| { |
| node::remove(i->second.root, first, last, this); |
| } |
| else if (i->second.data) |
| { |
| this->delete_data(i->second.data); |
| i->second.data = 0; |
| } |
| if (i->second.data == 0 && i->second.root == 0) |
| { |
| map.erase(i); |
| } |
| } |
| } |
| } |
| |
| void clear() |
| { |
| BOOST_FOREACH(typename map_type::value_type& x, map) |
| { |
| node::destruct_node(x.second.root, this); |
| if (x.second.data) |
| this->delete_data(x.second.data); |
| } |
| map.clear(); |
| } |
| |
| template <typename F> |
| void for_each(F f) const |
| { |
| BOOST_FOREACH(typename map_type::value_type const& x, map) |
| { |
| std::basic_string<Char> s(1, x.first); |
| node::for_each(x.second.root, s, f); |
| if (x.second.data) |
| f(s, *x.second.data); |
| } |
| } |
| |
| private: |
| |
| friend struct detail::tst_node<Char, T>; |
| |
| struct map_data |
| { |
| node* root; |
| T* data; |
| }; |
| |
| typedef unordered_map<Char, map_data> map_type; |
| |
| void copy(tst_map const& rhs) |
| { |
| BOOST_FOREACH(typename map_type::value_type const& x, rhs.map) |
| { |
| map_data xx = {node::clone_node(x.second.root, this), 0}; |
| if (x.second.data) |
| xx.data = data_pool.construct(*x.second.data); |
| map[x.first] = xx; |
| } |
| } |
| |
| tst_map& assign(tst_map const& rhs) |
| { |
| if (this != &rhs) |
| { |
| BOOST_FOREACH(typename map_type::value_type& x, map) |
| { |
| node::destruct_node(x.second.root, this); |
| } |
| map.clear(); |
| copy(rhs); |
| } |
| return *this; |
| } |
| |
| node* new_node(Char id) |
| { |
| return node_pool.construct(id); |
| } |
| |
| T* new_data(typename boost::call_traits<T>::param_type val) |
| { |
| return data_pool.construct(val); |
| } |
| |
| void delete_node(node* p) |
| { |
| node_pool.destroy(p); |
| } |
| |
| void delete_data(T* p) |
| { |
| data_pool.destroy(p); |
| } |
| |
| map_type map; |
| object_pool<node> node_pool; |
| object_pool<T> data_pool; |
| }; |
| }}} |
| |
| #endif |