/*============================================================================= | |
Copyright (c) 2001-2011 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 |