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