/////////////////////////////////////////////////////////////////////////////// | |
// results_cache.hpp | |
// | |
// Copyright 2008 Eric Niebler. 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) | |
#ifndef BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005 | |
#define BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005 | |
// MS compatible compilers support #pragma once | |
#if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
# pragma once | |
#endif | |
#include <cstddef> | |
#include <boost/detail/workaround.hpp> | |
#include <boost/assert.hpp> | |
#include <boost/xpressive/detail/detail_fwd.hpp> | |
#include <boost/xpressive/detail/core/list.hpp> | |
#include <boost/xpressive/detail/core/access.hpp> | |
#include <boost/xpressive/match_results.hpp> | |
namespace boost { namespace xpressive { namespace detail | |
{ | |
/////////////////////////////////////////////////////////////////////////////// | |
// nested_results | |
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) | |
template<typename BidiIter> | |
struct nested_results | |
: detail::list<match_results<BidiIter> > | |
{ | |
friend struct results_cache<BidiIter>; | |
friend struct match_results<BidiIter>; | |
}; | |
#else | |
template<typename BidiIter> | |
struct nested_results | |
: private detail::list<match_results<BidiIter> > | |
{ | |
friend struct results_cache<BidiIter>; | |
friend struct xpressive::match_results<BidiIter>; | |
typedef list<xpressive::match_results<BidiIter> > base_type; | |
typedef typename base_type::iterator iterator; | |
typedef typename base_type::const_iterator const_iterator; | |
typedef typename base_type::pointer pointer; | |
typedef typename base_type::const_pointer const_pointer; | |
typedef typename base_type::reference reference; | |
typedef typename base_type::const_reference const_reference; | |
typedef typename base_type::size_type size_type; | |
using base_type::begin; | |
using base_type::end; | |
using base_type::size; | |
using base_type::empty; | |
using base_type::front; | |
using base_type::back; | |
}; | |
#endif | |
/////////////////////////////////////////////////////////////////////////////// | |
// results_cache | |
// | |
// cache storage for reclaimed match_results structs | |
template<typename BidiIter> | |
struct results_cache | |
{ | |
typedef core_access<BidiIter> access; | |
match_results<BidiIter> &append_new(nested_results<BidiIter> &out) | |
{ | |
if(this->cache_.empty()) | |
{ | |
out.push_back(match_results<BidiIter>()); | |
} | |
else | |
{ | |
BOOST_ASSERT(access::get_nested_results(this->cache_.back()).empty()); | |
out.splice(out.end(), this->cache_, --this->cache_.end()); | |
} | |
return out.back(); | |
} | |
// move the last match_results struct into the cache | |
void reclaim_last(nested_results<BidiIter> &out) | |
{ | |
BOOST_ASSERT(!out.empty()); | |
// first, reclaim any nested results | |
nested_results<BidiIter> &nested = access::get_nested_results(out.back()); | |
if(!nested.empty()) | |
{ | |
this->reclaim_all(nested); | |
} | |
// then, reclaim the last match_results | |
this->cache_.splice(this->cache_.end(), out, --out.end()); | |
} | |
// move the last n match_results structs into the cache | |
void reclaim_last_n(nested_results<BidiIter> &out, std::size_t count) | |
{ | |
for(; 0 != count; --count) | |
{ | |
this->reclaim_last(out); | |
} | |
} | |
void reclaim_all(nested_results<BidiIter> &out) | |
{ | |
typedef typename nested_results<BidiIter>::iterator iter_type; | |
// first, recursively reclaim all the nested results | |
for(iter_type begin = out.begin(); begin != out.end(); ++begin) | |
{ | |
nested_results<BidiIter> &nested = access::get_nested_results(*begin); | |
if(!nested.empty()) | |
{ | |
this->reclaim_all(nested); | |
} | |
} | |
// next, reclaim the results themselves | |
this->cache_.splice(this->cache_.end(), out); | |
} | |
private: | |
nested_results<BidiIter> cache_; | |
}; | |
}}} // namespace boost::xpressive::detail | |
#endif |