// Copyright (c) 2001-2012 Hartmut Kaiser
|
//
|
// 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_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM)
|
#define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM
|
|
#include <boost/config.hpp>
|
#include <boost/type_traits/is_empty.hpp>
|
|
namespace boost { namespace spirit { namespace iterator_policies
|
{
|
///////////////////////////////////////////////////////////////////////////
|
// The purpose of the multi_pass_unique template is to eliminate
|
// empty policy classes (policies not containing any data items) from the
|
// multiple inheritance chain. This is necessary since some compilers
|
// fail to apply the empty base optimization if multiple inheritance is
|
// involved.
|
// Additionally this can be used to combine separate policies into one
|
// single multi_pass_policy as required by the multi_pass template
|
///////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////
|
// select the correct derived classes based on if a policy is empty
|
template <typename T
|
, typename Ownership, typename Checking, typename Input, typename Storage
|
, bool OwnershipIsEmpty = boost::is_empty<Ownership>::value
|
, bool CheckingIsEmpty = boost::is_empty<Checking>::value
|
, bool InputIsEmpty = boost::is_empty<Input>::value>
|
struct multi_pass_unique;
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, false, false, false>
|
: Ownership, Checking, Input, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T& x) : Input(x) {}
|
multi_pass_unique(T const& x) : Input(x) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Ownership::destroy(mp);
|
Checking::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Ownership::swap(x);
|
this->Checking::swap(x);
|
this->Input::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, false, false, true>
|
: Ownership, Checking, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T const&) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Ownership::destroy(mp);
|
Checking::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Ownership::swap(x);
|
this->Checking::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// implement input policy functions by forwarding to the Input type
|
template <typename MultiPass>
|
inline static void advance_input(MultiPass& mp)
|
{ Input::advance_input(mp); }
|
|
template <typename MultiPass>
|
inline static typename MultiPass::reference get_input(MultiPass& mp)
|
{ return Input::get_input(mp); }
|
|
template <typename MultiPass>
|
inline static bool input_at_eof(MultiPass const& mp)
|
{ return Input::input_at_eof(mp); }
|
|
template <typename MultiPass, typename TokenType>
|
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
{ return Input::input_is_valid(mp, curtok); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, false, true, false>
|
: Ownership, Input, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T& x) : Input(x) {}
|
multi_pass_unique(T const& x) : Input(x) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Ownership::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Ownership::swap(x);
|
this->Input::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// checking policy functions are forwarded to the Checking type
|
template <typename MultiPass>
|
inline static void docheck(MultiPass const& mp)
|
{ Checking::docheck(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, false, true, true>
|
: Ownership, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T const&) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Ownership::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Ownership::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// implement input policy functions by forwarding to the Input type
|
template <typename MultiPass>
|
inline static void advance_input(MultiPass& mp)
|
{ Input::advance_input(mp); }
|
|
template <typename MultiPass>
|
inline static typename MultiPass::reference get_input(MultiPass& mp)
|
{ return Input::get_input(mp); }
|
|
template <typename MultiPass>
|
inline static bool input_at_eof(MultiPass const& mp)
|
{ return Input::input_at_eof(mp); }
|
|
template <typename MultiPass, typename TokenType>
|
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
{ return Input::input_is_valid(mp, curtok); }
|
|
// checking policy functions are forwarded to the Checking type
|
template <typename MultiPass>
|
inline static void docheck(MultiPass const& mp)
|
{ Checking::docheck(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, true, false, false>
|
: Checking, Input, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T& x) : Input(x) {}
|
multi_pass_unique(T const& x) : Input(x) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Checking::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Checking::swap(x);
|
this->Input::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// ownership policy functions are forwarded to the Ownership type
|
template <typename MultiPass>
|
inline static void clone(MultiPass& mp)
|
{ Ownership::clone(mp); }
|
|
template <typename MultiPass>
|
inline static bool release(MultiPass& mp)
|
{ return Ownership::release(mp); }
|
|
template <typename MultiPass>
|
inline static bool is_unique(MultiPass const& mp)
|
{ return Ownership::is_unique(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, true, false, true>
|
: Checking, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T const&) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Checking::destroy(mp);
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Checking::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// implement input policy functions by forwarding to the Input type
|
template <typename MultiPass>
|
inline static void advance_input(MultiPass& mp)
|
{ Input::advance_input(mp); }
|
|
template <typename MultiPass>
|
inline static typename MultiPass::reference get_input(MultiPass& mp)
|
{ return Input::get_input(mp); }
|
|
template <typename MultiPass>
|
inline static bool input_at_eof(MultiPass const& mp)
|
{ return Input::input_at_eof(mp); }
|
|
template <typename MultiPass, typename TokenType>
|
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
{ return Input::input_is_valid(mp, curtok); }
|
|
// ownership policy functions are forwarded to the Ownership type
|
template <typename MultiPass>
|
inline static void clone(MultiPass& mp)
|
{ Ownership::clone(mp); }
|
|
template <typename MultiPass>
|
inline static bool release(MultiPass& mp)
|
{ return Ownership::release(mp); }
|
|
template <typename MultiPass>
|
inline static bool is_unique(MultiPass const& mp)
|
{ return Ownership::is_unique(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, true, true, false>
|
: Input, Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T& x) : Input(x) {}
|
multi_pass_unique(T const& x) : Input(x) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Input::swap(x);
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// checking policy functions are forwarded to the Checking type
|
template <typename MultiPass>
|
inline static void docheck(MultiPass const& mp)
|
{ Checking::docheck(mp); }
|
|
// ownership policy functions are forwarded to the Ownership type
|
template <typename MultiPass>
|
inline static void clone(MultiPass& mp)
|
{ Ownership::clone(mp); }
|
|
template <typename MultiPass>
|
inline static bool release(MultiPass& mp)
|
{ return Ownership::release(mp); }
|
|
template <typename MultiPass>
|
inline static bool is_unique(MultiPass const& mp)
|
{ return Ownership::is_unique(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
template <typename T, typename Ownership, typename Checking
|
, typename Input, typename Storage>
|
struct multi_pass_unique<T, Ownership, Checking, Input, Storage
|
, true, true, true>
|
: Storage
|
{
|
multi_pass_unique() {}
|
multi_pass_unique(T const&) {}
|
|
template <typename MultiPass>
|
static void destroy(MultiPass& mp)
|
{
|
Input::destroy(mp);
|
Storage::destroy(mp);
|
}
|
|
void swap(multi_pass_unique& x)
|
{
|
this->Storage::swap(x);
|
}
|
|
template <typename MultiPass>
|
inline static void clear_queue(MultiPass& mp)
|
{
|
Checking::clear_queue(mp);
|
Storage::clear_queue(mp);
|
}
|
|
// implement input policy functions by forwarding to the Input type
|
template <typename MultiPass>
|
inline static void advance_input(MultiPass& mp)
|
{ Input::advance_input(mp); }
|
|
template <typename MultiPass>
|
inline static typename MultiPass::reference get_input(MultiPass& mp)
|
{ return Input::get_input(mp); }
|
|
template <typename MultiPass>
|
inline static bool input_at_eof(MultiPass const& mp)
|
{ return Input::input_at_eof(mp); }
|
|
template <typename MultiPass, typename TokenType>
|
inline static bool input_is_valid(MultiPass& mp, TokenType& curtok)
|
{ return Input::input_is_valid(mp, curtok); }
|
|
// checking policy functions are forwarded to the Checking type
|
template <typename MultiPass>
|
inline static void docheck(MultiPass const& mp)
|
{ Checking::docheck(mp); }
|
|
// ownership policy functions are forwarded to the Ownership type
|
template <typename MultiPass>
|
inline static void clone(MultiPass& mp)
|
{ Ownership::clone(mp); }
|
|
template <typename MultiPass>
|
inline static bool release(MultiPass& mp)
|
{ return Ownership::release(mp); }
|
|
template <typename MultiPass>
|
inline static bool is_unique(MultiPass const& mp)
|
{ return Ownership::is_unique(mp); }
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
// the multi_pass_shared structure is used to combine the shared data items
|
// of all policies into one single structure
|
///////////////////////////////////////////////////////////////////////////
|
template<typename T, typename Ownership, typename Checking, typename Input
|
, typename Storage>
|
struct multi_pass_shared : Ownership, Checking, Input, Storage
|
{
|
explicit multi_pass_shared(T& input) : Input(input) {}
|
explicit multi_pass_shared(T const& input) : Input(input) {}
|
};
|
|
///////////////////////////////////////////////////////////////////////////
|
// This is a default implementation of a policy class as required by the
|
// multi_pass template, combining 4 separate policies into one. Any other
|
// multi_pass policy class needs to follow the scheme as shown below.
|
template<typename Ownership, typename Checking, typename Input
|
, typename Storage>
|
struct default_policy
|
{
|
typedef Ownership ownership_policy;
|
typedef Checking checking_policy;
|
typedef Input input_policy;
|
typedef Storage storage_policy;
|
|
///////////////////////////////////////////////////////////////////////
|
template <typename T>
|
struct unique : multi_pass_unique<T
|
, typename Ownership::unique, typename Checking::unique
|
, typename Input::BOOST_NESTED_TEMPLATE unique<T>
|
, typename Storage::BOOST_NESTED_TEMPLATE unique<
|
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
|
{
|
typedef typename Ownership::unique ownership_policy;
|
typedef typename Checking::unique checking_policy;
|
typedef typename Input::BOOST_NESTED_TEMPLATE unique<T>
|
input_policy;
|
typedef typename Storage::BOOST_NESTED_TEMPLATE unique<
|
typename input_policy::value_type> storage_policy;
|
|
typedef multi_pass_unique<T, ownership_policy, checking_policy
|
, input_policy, storage_policy> unique_base_type;
|
|
unique() {}
|
explicit unique(T& input) : unique_base_type(input) {}
|
explicit unique(T const& input) : unique_base_type(input) {}
|
};
|
|
///////////////////////////////////////////////////////////////////////
|
template <typename T>
|
struct shared : multi_pass_shared<T
|
, typename Ownership::shared, typename Checking::shared
|
, typename Input::BOOST_NESTED_TEMPLATE shared<T>
|
, typename Storage::BOOST_NESTED_TEMPLATE shared<
|
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> >
|
{
|
typedef typename Ownership::shared ownership_policy;
|
typedef typename Checking::shared checking_policy;
|
typedef typename Input::BOOST_NESTED_TEMPLATE shared<T>
|
input_policy;
|
typedef typename Storage::BOOST_NESTED_TEMPLATE shared<
|
typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type>
|
storage_policy;
|
|
typedef multi_pass_shared<T, ownership_policy, checking_policy
|
, input_policy, storage_policy> shared_base_type;
|
|
explicit shared(T& input)
|
: shared_base_type(input), inhibit_clear_queue_(false) {}
|
explicit shared(T const& input)
|
: shared_base_type(input), inhibit_clear_queue_(false) {}
|
|
// This is needed for the correct implementation of expectation
|
// points. Normally expectation points flush any multi_pass
|
// iterator they may act on, but if the corresponding error handler
|
// is of type 'retry' no flushing of the internal buffers should be
|
// executed (even if explicitly requested).
|
bool inhibit_clear_queue_;
|
};
|
};
|
|
}}}
|
|
#endif
|