224 lines
6.3 KiB
C++
224 lines
6.3 KiB
C++
|
/*=============================================================================
|
||
|
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/tst.hpp>
|
||
|
#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
|
||
|
{
|
||
|
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())
|
||
|
{
|
||
|
if (T* p = node::find(i->second.root, first, last, filter))
|
||
|
{
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
if (i->second.data)
|
||
|
{
|
||
|
return i->second.data;
|
||
|
}
|
||
|
}
|
||
|
first = save;
|
||
|
}
|
||
|
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()
|
||
|
{
|
||
|
typedef typename map_type::iterator iter_t;
|
||
|
for (iter_t it = map.begin(), end = map.end(); it != end; ++it)
|
||
|
{
|
||
|
node::destruct_node(it->second.root, this);
|
||
|
if (it->second.data)
|
||
|
this->delete_data(it->second.data);
|
||
|
}
|
||
|
map.clear();
|
||
|
}
|
||
|
|
||
|
template <typename F>
|
||
|
void for_each(F f) const
|
||
|
{
|
||
|
typedef typename map_type::const_iterator iter_t;
|
||
|
for (iter_t it = map.begin(), end = map.end(); it != end; ++it)
|
||
|
{
|
||
|
std::basic_string<Char> s(1, it->first);
|
||
|
node::for_each(it->second.root, s, f);
|
||
|
if (it->second.data)
|
||
|
f(s, *it->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)
|
||
|
{
|
||
|
typedef typename map_type::const_iterator iter_t;
|
||
|
for (iter_t it = rhs.map.begin(), end = rhs.map.end(); it != end; ++it)
|
||
|
{
|
||
|
map_data xx = {node::clone_node(it->second.root, this), 0};
|
||
|
if (it->second.data)
|
||
|
xx.data = data_pool.construct(*it->second.data);
|
||
|
map[it->first] = xx;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tst_map& assign(tst_map const& rhs)
|
||
|
{
|
||
|
if (this != &rhs)
|
||
|
{
|
||
|
typedef typename map_type::const_iterator iter_t;
|
||
|
for (iter_t it = map.begin(), end = map.end(); it != end; ++it)
|
||
|
{
|
||
|
node::destruct_node(it->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
|