You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
216 lines
5.9 KiB
216 lines
5.9 KiB
/*============================================================================= |
|
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
|
|
|