Imported existing code
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <exception> // for std::exception
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class illegal_backtracking
|
||||
// thrown by buf_id_check CheckingPolicy if an instance of an iterator is
|
||||
// used after another one has invalidated the queue
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class illegal_backtracking : public std::exception
|
||||
{
|
||||
public:
|
||||
illegal_backtracking() throw() {}
|
||||
~illegal_backtracking() throw() {}
|
||||
|
||||
char const* what() const throw()
|
||||
{
|
||||
return "boost::spirit::multi_pass::illegal_backtracking";
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// class buf_id_check
|
||||
// Implementation of the CheckingPolicy used by multi_pass
|
||||
// This policy is most effective when used together with the std_deque
|
||||
// StoragePolicy.
|
||||
//
|
||||
// If used with the fixed_size_queue StoragePolicy, it will not detect
|
||||
// iterator dereferences that are out of the range of the queue.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct buf_id_check
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique //: detail::default_checking_policy
|
||||
{
|
||||
unique()
|
||||
: buf_id(0)
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: buf_id(x.buf_id)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(buf_id, x.buf_id);
|
||||
}
|
||||
|
||||
// called to verify that everything is ok.
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const& mp)
|
||||
{
|
||||
if (mp.buf_id != mp.shared->shared_buf_id)
|
||||
boost::throw_exception(illegal_backtracking());
|
||||
}
|
||||
|
||||
// called from multi_pass::clear_queue, so we can increment the count
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass& mp)
|
||||
{
|
||||
++mp.shared->shared_buf_id;
|
||||
++mp.buf_id;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
|
||||
protected:
|
||||
unsigned long buf_id;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
shared() : shared_buf_id(0) {}
|
||||
unsigned long shared_buf_id;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,480 @@
|
||||
// Copyright (c) 2001-2008, 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/type_traits/is_empty.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_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 a compiler is not
|
||||
// allowed to apply the empty base optimization if multiple inheritance is
|
||||
// involved (or at least most compilers fail to apply it).
|
||||
// Additionally this can be used to combine separate policies into one
|
||||
// single multi_pass_policy as required by the multi_pass template
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
// without partial template specialization there is nothing much to do in
|
||||
// terms of empty base optimization anyways...
|
||||
template <typename T, typename Ownership, typename Checking,
|
||||
typename Input, typename Storage>
|
||||
struct multi_pass_unique
|
||||
: Ownership, Checking, Input, Storage
|
||||
{
|
||||
multi_pass_unique() {}
|
||||
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);
|
||||
}
|
||||
};
|
||||
#else
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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 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 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& 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->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(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& 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->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
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 check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::clear_queue(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 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);
|
||||
}
|
||||
|
||||
// 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& 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->Storage::swap(x);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
// checking policy functions are forwarded to the Checking type
|
||||
template <typename MultiPass>
|
||||
inline static void check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::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, 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);
|
||||
}
|
||||
|
||||
// implement input policy functions by forwarding to the Input type
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static TokenType& advance_input(MultiPass& mp, TokenType& curtok)
|
||||
{ return Input::advance_input(mp, curtok); }
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
inline static bool input_at_eof(MultiPass const& mp, TokenType& curtok)
|
||||
{ return Input::input_at_eof(mp, curtok); }
|
||||
|
||||
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 check(MultiPass const& mp)
|
||||
{ Checking::check(mp); }
|
||||
|
||||
template <typename MultiPass>
|
||||
inline static void clear_queue(MultiPass& mp)
|
||||
{ Checking::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); }
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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 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 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 const& input) : shared_base_type(input) {}
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_FIRST_OWNER_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIRST_OWNER_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class first_owner
|
||||
// Implementation of an OwnershipPolicy used by multi_pass
|
||||
// This ownership policy dictates that the first iterator created will
|
||||
// determine the lifespan of the shared components. This works well for
|
||||
// spirit, since no dynamic allocation of iterators is done, and all
|
||||
// copies are make on the stack.
|
||||
//
|
||||
// There is a caveat about using this policy together with the std_deque
|
||||
// StoragePolicy. Since first_owner always returns false from unique(),
|
||||
// std_deque will only release the queued data if clear_queue() is called.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct first_owner
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : detail::default_ownership_policy
|
||||
{
|
||||
unique()
|
||||
: first(true)
|
||||
{}
|
||||
|
||||
unique(unique const&)
|
||||
: first(false)
|
||||
{}
|
||||
|
||||
// return true to indicate deletion of resources
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp)
|
||||
{
|
||||
return mp.first;
|
||||
}
|
||||
|
||||
// use swap from default policy
|
||||
// if we're the first, we still remain the first, even if assigned
|
||||
// to, so don't swap first_. swap is only called from operator=
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const&)
|
||||
{
|
||||
return false; // no way to know, so always return false
|
||||
}
|
||||
|
||||
protected:
|
||||
bool first;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
// no shared data
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,388 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_FIXED_SIZE_QUEUE_MAR_16_2007_1137AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_MAR_16_2007_1137AM
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp> // for BOOST_ASSERT
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Make sure we're using a decent version of the Boost.IteratorAdaptors lib
|
||||
#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
|
||||
BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
|
||||
#error "Please use at least Boost V1.31.0 while compiling the fixed_size_queue class!"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define BOOST_SPIRIT_ASSERT_FSQ_SIZE \
|
||||
BOOST_ASSERT(((m_tail + N + 1) - m_head) % (N+1) == m_size % (N+1)) \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Queue, typename T, typename Pointer>
|
||||
class fsq_iterator
|
||||
: public boost::iterator_adaptor<
|
||||
fsq_iterator<Queue, T, Pointer>, Pointer, T,
|
||||
std::random_access_iterator_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef typename Queue::position_type position_type;
|
||||
typedef boost::iterator_adaptor<
|
||||
fsq_iterator<Queue, T, Pointer>, Pointer, T,
|
||||
std::random_access_iterator_tag
|
||||
> base_type;
|
||||
|
||||
fsq_iterator() {}
|
||||
fsq_iterator(position_type const &p_) : p(p_) {}
|
||||
|
||||
position_type const &get_position() const { return p; }
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
typename base_type::reference dereference() const
|
||||
{
|
||||
return p.self->m_queue[p.pos];
|
||||
}
|
||||
|
||||
void increment()
|
||||
{
|
||||
++p.pos;
|
||||
if (p.pos == Queue::MAX_SIZE+1)
|
||||
p.pos = 0;
|
||||
}
|
||||
|
||||
void decrement()
|
||||
{
|
||||
if (p.pos == 0)
|
||||
p.pos = Queue::MAX_SIZE;
|
||||
else
|
||||
--p.pos;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherDerived, typename OtherIterator,
|
||||
typename V, typename C, typename R, typename D
|
||||
>
|
||||
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D>
|
||||
const &x) const
|
||||
{
|
||||
position_type const &rhs_pos =
|
||||
static_cast<OtherDerived const &>(x).get_position();
|
||||
return (p.self == rhs_pos.self) && (p.pos == rhs_pos.pos);
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherDerived, typename OtherIterator,
|
||||
typename V, typename C, typename R, typename D
|
||||
>
|
||||
typename base_type::difference_type distance_to(
|
||||
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D>
|
||||
const &x) const
|
||||
{
|
||||
typedef typename base_type::difference_type difference_type;
|
||||
|
||||
position_type const &p2 =
|
||||
static_cast<OtherDerived const &>(x).get_position();
|
||||
std::size_t pos1 = p.pos;
|
||||
std::size_t pos2 = p2.pos;
|
||||
|
||||
// Undefined behavior if the iterators come from different
|
||||
// containers
|
||||
BOOST_ASSERT(p.self == p2.self);
|
||||
|
||||
if (pos1 < p.self->m_head)
|
||||
pos1 += Queue::MAX_SIZE;
|
||||
if (pos2 < p2.self->m_head)
|
||||
pos2 += Queue::MAX_SIZE;
|
||||
|
||||
if (pos2 > pos1)
|
||||
return difference_type(pos2 - pos1);
|
||||
else
|
||||
return -difference_type(pos1 - pos2);
|
||||
}
|
||||
|
||||
void advance(typename base_type::difference_type n)
|
||||
{
|
||||
// Notice that we don't care values of n that can
|
||||
// wrap around more than one time, since it would
|
||||
// be undefined behavior anyway (going outside
|
||||
// the begin/end range). Negative wrapping is a bit
|
||||
// cumbersome because we don't want to case p.pos
|
||||
// to signed.
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
if (p.pos < (std::size_t)n)
|
||||
p.pos = Queue::MAX_SIZE+1 - (n - p.pos);
|
||||
else
|
||||
p.pos -= n;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.pos += n;
|
||||
if (p.pos >= Queue::MAX_SIZE+1)
|
||||
p.pos -= Queue::MAX_SIZE+1;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
position_type p;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, std::size_t N>
|
||||
class fixed_size_queue
|
||||
{
|
||||
private:
|
||||
struct position
|
||||
{
|
||||
fixed_size_queue* self;
|
||||
std::size_t pos;
|
||||
|
||||
position() : self(0), pos(0) {}
|
||||
|
||||
// The const_cast here is just to avoid to have two different
|
||||
// position structures for the const and non-const case.
|
||||
// The const semantic is guaranteed by the iterator itself
|
||||
position(const fixed_size_queue* s, std::size_t p)
|
||||
: self(const_cast<fixed_size_queue*>(s)), pos(p)
|
||||
{}
|
||||
};
|
||||
|
||||
public:
|
||||
// Declare the iterators
|
||||
typedef fsq_iterator<fixed_size_queue<T, N>, T, T*> iterator;
|
||||
typedef
|
||||
fsq_iterator<fixed_size_queue<T, N>, T const, T const*>
|
||||
const_iterator;
|
||||
typedef position position_type;
|
||||
|
||||
friend class fsq_iterator<fixed_size_queue<T, N>, T, T*>;
|
||||
friend class fsq_iterator<fixed_size_queue<T, N>, T const, T const*>;
|
||||
|
||||
fixed_size_queue();
|
||||
fixed_size_queue(const fixed_size_queue& x);
|
||||
fixed_size_queue& operator=(const fixed_size_queue& x);
|
||||
~fixed_size_queue();
|
||||
|
||||
void push_back(const T& e);
|
||||
void push_front(const T& e);
|
||||
void serve(T& e);
|
||||
void pop_front();
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return m_size == N;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(position(this, m_head));
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(position(this, m_head));
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(position(this, m_tail));
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return const_iterator(position(this, m_tail));
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
T& front()
|
||||
{
|
||||
return m_queue[m_head];
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
{
|
||||
return m_queue[m_head];
|
||||
}
|
||||
|
||||
private:
|
||||
// Redefine the template parameters to avoid using partial template
|
||||
// specialization on the iterator policy to extract N.
|
||||
BOOST_STATIC_CONSTANT(std::size_t, MAX_SIZE = N);
|
||||
|
||||
std::size_t m_head;
|
||||
std::size_t m_tail;
|
||||
std::size_t m_size;
|
||||
T m_queue[N+1];
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::fixed_size_queue()
|
||||
: m_head(0)
|
||||
, m_tail(0)
|
||||
, m_size(0)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::fixed_size_queue(const fixed_size_queue& x)
|
||||
: m_head(x.m_head)
|
||||
, m_tail(x.m_tail)
|
||||
, m_size(x.m_size)
|
||||
{
|
||||
copy(x.begin(), x.end(), begin());
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline fixed_size_queue<T, N>&
|
||||
fixed_size_queue<T, N>::operator=(const fixed_size_queue& x)
|
||||
{
|
||||
if (this != &x)
|
||||
{
|
||||
m_head = x.m_head;
|
||||
m_tail = x.m_tail;
|
||||
m_size = x.m_size;
|
||||
copy(x.begin(), x.end(), begin());
|
||||
}
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline
|
||||
fixed_size_queue<T, N>::~fixed_size_queue()
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::push_back(const T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
BOOST_ASSERT(!full());
|
||||
|
||||
m_queue[m_tail] = e;
|
||||
++m_size;
|
||||
++m_tail;
|
||||
if (m_tail == N+1)
|
||||
m_tail = 0;
|
||||
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::push_front(const T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
BOOST_ASSERT(!full());
|
||||
|
||||
if (m_head == 0)
|
||||
m_head = N;
|
||||
else
|
||||
--m_head;
|
||||
|
||||
m_queue[m_head] = e;
|
||||
++m_size;
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::serve(T& e)
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
e = m_queue[m_head];
|
||||
pop_front();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
inline void
|
||||
fixed_size_queue<T, N>::pop_front()
|
||||
{
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
|
||||
++m_head;
|
||||
if (m_head == N+1)
|
||||
m_head = 0;
|
||||
--m_size;
|
||||
|
||||
BOOST_ASSERT(m_size <= N+1);
|
||||
BOOST_SPIRIT_ASSERT_FSQ_SIZE;
|
||||
BOOST_ASSERT(m_head <= N+1);
|
||||
BOOST_ASSERT(m_tail <= N+1);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#undef BOOST_SPIRIT_ASSERT_FSQ_SIZE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_FIXED_SIZE_QUEUE_POLICY_MAR_16_2007_1134AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/fixed_size_queue.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class fixed_size_queue
|
||||
// Implementation of the StoragePolicy used by multi_pass
|
||||
// fixed_size_queue keeps a circular buffer (implemented by
|
||||
// boost::spirit::fixed_size_queue class) that is size N+1 and stores N
|
||||
// elements.
|
||||
//
|
||||
// It is up to the user to ensure that there is enough look ahead for
|
||||
// their grammar. Currently there is no way to tell if an iterator is
|
||||
// pointing to forgotten data. The leading iterator will put an item in
|
||||
// the queue and remove one when it is incremented. No dynamic allocation
|
||||
// is done, except on creation of the queue (fixed_size_queue constructor).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <std::size_t N>
|
||||
struct fixed_size_queue
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
class unique : public detail::default_storage_policy
|
||||
{
|
||||
private:
|
||||
typedef detail::fixed_size_queue<Value, N> queue_type;
|
||||
|
||||
protected:
|
||||
unique()
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: queuePosition(x.queuePosition)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(queuePosition, x.queuePosition);
|
||||
}
|
||||
|
||||
// This is called when the iterator is dereferenced. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and access the m_input data member.
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference
|
||||
dereference(MultiPass const& mp)
|
||||
{
|
||||
if (mp.queuePosition == mp.shared->queuedElements.end())
|
||||
{
|
||||
return MultiPass::get_input(mp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *mp.queuePosition;
|
||||
}
|
||||
}
|
||||
|
||||
// This is called when the iterator is incremented. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and access the m_input data member.
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass& mp)
|
||||
{
|
||||
if (mp.queuePosition == mp.shared->queuedElements.end())
|
||||
{
|
||||
// don't let the queue get larger than N
|
||||
if (mp.shared->queuedElements.size() >= N)
|
||||
mp.shared->queuedElements.pop_front();
|
||||
|
||||
mp.shared->queuedElements.push_back(MultiPass::get_input(mp));
|
||||
MultiPass::advance_input(mp);
|
||||
}
|
||||
++mp.queuePosition;
|
||||
}
|
||||
|
||||
// clear_queue is a no-op
|
||||
|
||||
// called to determine whether the iterator is an eof iterator
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp)
|
||||
{
|
||||
return mp.queuePosition == mp.shared->queuedElements.end() &&
|
||||
MultiPass::input_at_eof(mp);
|
||||
}
|
||||
|
||||
// called by operator==
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queuePosition == x.queuePosition;
|
||||
}
|
||||
|
||||
// called by operator<
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queuePosition < x.queuePosition;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable typename queue_type::iterator queuePosition;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
struct shared
|
||||
{
|
||||
typedef detail::fixed_size_queue<Value, N> queue_type;
|
||||
queue_type queuedElements;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2001-2008, 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_SPLIT_FUNCTOR_INPUT_POLICY_JAN_16_2008_0448M)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_16_2008_0448M
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class functor_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
// functor_input gets tokens from a functor
|
||||
//
|
||||
// Note: the functor must have a typedef for result_type
|
||||
// It also must have a static variable of type result_type defined
|
||||
// to represent EOF that is called eof.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct functor_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
private:
|
||||
typedef typename Functor::result_type result_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const& x) : ftor(x) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(ftor, x.ftor);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
public:
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
t = mp.ftor();
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
return t == mp.ftor.eof;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
using namespace is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
Functor& get_functor() const
|
||||
{
|
||||
return ftor;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable Functor ftor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(Functor const& x) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_INPUT_ITERATOR_POLICY_MAR_16_2007_1156AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_INPUT_ITERATOR_POLICY_MAR_16_2007_1156AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace input_iterator_is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class input_iterator
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
//
|
||||
// The input_iterator encapsulates an input iterator of type T
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct input_iterator
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
private:
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::value_type
|
||||
result_type;
|
||||
|
||||
public:
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::difference_type
|
||||
difference_type;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::distance_type
|
||||
distance_type;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::pointer
|
||||
pointer;
|
||||
typedef
|
||||
typename boost::detail::iterator_traits<T>::reference
|
||||
reference;
|
||||
typedef result_type value_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(T x) : input(x) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(input, x.input);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
t = *++mp.input;
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const&)
|
||||
{
|
||||
return mp.input == T();
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
using namespace input_iterator_is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
protected:
|
||||
T input;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(T) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_LEX_INPUT_POLICY_MAR_16_2007_1205PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_LEX_INPUT_POLICY_MAR_16_2007_1205PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// class lex_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
//
|
||||
// The lex_input class gets tokens (integers) from yylex()
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct lex_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class unique : public detail::default_input_policy
|
||||
{
|
||||
public:
|
||||
typedef int value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef int* pointer;
|
||||
typedef int& reference;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(T) {}
|
||||
|
||||
public:
|
||||
template <typename MultiPass>
|
||||
static void advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// if mp.shared is NULL then this instance of the multi_pass
|
||||
// represents a end iterator, so no advance functionality is
|
||||
// needed
|
||||
if (0 != mp.shared)
|
||||
{
|
||||
extern int yylex();
|
||||
t = yylex();
|
||||
}
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return 0 == t;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return -1 != t;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(T) {}
|
||||
|
||||
// no shared data elements
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_MULTI_PASS_MAR_16_2007_1122AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1122AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
inline void swap(T& t1, T& t2)
|
||||
{
|
||||
using std::swap;
|
||||
using boost::spirit::swap;
|
||||
swap(t1, t2);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Meta-function to generate a std::iterator<> base class for multi_pass.
|
||||
// This is used mainly to improve conformance of compilers not supporting
|
||||
// PTS and thus relying on inheritance to recognize an iterator.
|
||||
//
|
||||
// We are using boost::iterator<> because it offers an automatic
|
||||
// workaround for broken std::iterator<> implementations.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename InputPolicy>
|
||||
struct iterator_base_creator
|
||||
{
|
||||
typedef typename InputPolicy::BOOST_NESTED_TEMPLATE unique<T> input_type;
|
||||
|
||||
typedef boost::iterator <
|
||||
std::forward_iterator_tag,
|
||||
typename input_type::value_type,
|
||||
typename input_type::difference_type,
|
||||
typename input_type::pointer,
|
||||
typename input_type::reference
|
||||
> type;
|
||||
};
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Default implementations of the different policies to be used with a
|
||||
// multi_pass iterator
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct default_input_policy
|
||||
{
|
||||
default_input_policy() {}
|
||||
|
||||
template <typename Functor>
|
||||
default_input_policy(Functor const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_input_policy&) {}
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static TokenType& advance_input(MultiPass& mp, TokenType& curtok);
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static bool input_at_eof(MultiPass const& mp, TokenType& curtok);
|
||||
|
||||
template <typename MultiPass, typename TokenType>
|
||||
static bool input_is_valid(MultiPass& mp, TokenType& curtok);
|
||||
};
|
||||
|
||||
struct default_ownership_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_ownership_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clone(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const& mp);
|
||||
};
|
||||
|
||||
struct default_storage_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_storage_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference dereference(MultiPass const& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x);
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x);
|
||||
};
|
||||
|
||||
struct default_checking_policy
|
||||
{
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
|
||||
void swap(default_checking_policy&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_NO_CHECK_POLICY_MAR_16_2007_1121AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_NO_CHECK_POLICY_MAR_16_2007_1121AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class no_check
|
||||
// Implementation of the CheckingPolicy used by multi_pass
|
||||
// It does not do anything :-)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct no_check
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : public detail::default_checking_policy
|
||||
{
|
||||
void swap(unique&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void check(MultiPass const&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass&) {}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&) {}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_REF_COUNTED_POLICY_MAR_16_2007_1108AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_REF_COUNTED_POLICY_MAR_16_2007_1108AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class ref_counted
|
||||
// Implementation of an OwnershipPolicy used by multi_pass.
|
||||
//
|
||||
// Implementation modified from RefCounted class from the Loki library by
|
||||
// Andrei Alexandrescu.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct ref_counted
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
struct unique // : detail::default_ownership_policy
|
||||
{
|
||||
void swap(unique&) {}
|
||||
|
||||
// clone is called when a copy of the iterator is made, so
|
||||
// increment the ref-count.
|
||||
template <typename MultiPass>
|
||||
static void clone(MultiPass& mp)
|
||||
{
|
||||
if (0 != mp.shared)
|
||||
++mp.shared->count;
|
||||
}
|
||||
|
||||
// called when a copy is deleted. Decrement the ref-count. Return
|
||||
// value of true indicates that the last copy has been released.
|
||||
template <typename MultiPass>
|
||||
static bool release(MultiPass& mp)
|
||||
{
|
||||
return 0 != mp.shared && 0 == --mp.shared->count;
|
||||
}
|
||||
|
||||
// returns true if there is only one iterator in existence.
|
||||
// std_deque StoragePolicy will free it's buffered data if this
|
||||
// returns true.
|
||||
template <typename MultiPass>
|
||||
static bool is_unique(MultiPass const& mp)
|
||||
{
|
||||
return 0 == mp.shared || 1 == mp.shared->count;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
struct shared
|
||||
{
|
||||
shared() : count(1) {}
|
||||
std::size_t count;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2001-2008, 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_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
namespace split_functor_input_is_valid_test_
|
||||
{
|
||||
template <typename Token>
|
||||
inline bool token_is_valid(Token const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class split_functor_input
|
||||
// Implementation of the InputPolicy used by multi_pass
|
||||
// split_functor_input gets tokens from a functor
|
||||
//
|
||||
// This policy should be used when the functor hold two parts of data: a
|
||||
// unique part (unique for each instance of the iterator) and a shared
|
||||
// part (to be shared between the different copies of the same iterator).
|
||||
// Using this policy allows to merge the shared part of the functor with
|
||||
// the shared part of the iterator data, saving one pointer and one
|
||||
// allocation per iterator instance.
|
||||
//
|
||||
// The Functor template parameter of this policy is expected to be a
|
||||
// std::pair<unique, shared>, where 'unique' and 'shared' represent the
|
||||
// respective parts of the functor itself.
|
||||
//
|
||||
// Note: the unique part of the functor must have a typedef for result_type
|
||||
// It also must have a static variable of type result_type defined
|
||||
// to represent EOF that is called eof.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct split_functor_input
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
typename Functor,
|
||||
bool FunctorIsEmpty = is_empty<typename Functor::first_type>::value
|
||||
>
|
||||
class unique;
|
||||
|
||||
// the unique part of the functor is empty, do not include the functor
|
||||
// at all to avoid unnecessary padding bytes to be included into the
|
||||
// generated structure
|
||||
template <typename Functor>
|
||||
class unique<Functor, true> // : public detail::default_input_policy
|
||||
{
|
||||
protected:
|
||||
typedef typename Functor::first_type functor_type;
|
||||
typedef typename functor_type::result_type result_type;
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const&) {}
|
||||
|
||||
public:
|
||||
void swap(unique&) {}
|
||||
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static value_type& advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// passing the current token instance as a parameter helps
|
||||
// generating better code if compared to assigning the
|
||||
// result of the functor to this instance
|
||||
return functor_type::get_next(mp, t);
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const&, value_type const& t)
|
||||
{
|
||||
return t == functor_type::eof;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static bool input_is_valid(MultiPass const&, value_type const& t)
|
||||
{
|
||||
using namespace split_functor_input_is_valid_test_;
|
||||
return token_is_valid(t);
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass& mp)
|
||||
{
|
||||
functor_type::destroy(mp);
|
||||
}
|
||||
};
|
||||
|
||||
// the unique part of the functor is non-empty
|
||||
template <typename Functor>
|
||||
class unique<Functor, false> : public unique<Functor, true>
|
||||
{
|
||||
protected:
|
||||
typedef typename Functor::first_type functor_type;
|
||||
typedef typename functor_type::result_type result_type;
|
||||
|
||||
protected:
|
||||
unique() {}
|
||||
explicit unique(Functor const& x) : ftor(x.first) {}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(ftor, x.ftor);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef result_type value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::ptrdiff_t distance_type;
|
||||
typedef result_type* pointer;
|
||||
typedef result_type& reference;
|
||||
|
||||
public:
|
||||
// get the next token
|
||||
template <typename MultiPass>
|
||||
static value_type& advance_input(MultiPass& mp, value_type& t)
|
||||
{
|
||||
// passing the current token instance as a parameter helps
|
||||
// generating better code if compared to assigning the
|
||||
// result of the functor to this instance
|
||||
return mp.ftor.get_next(mp, t);
|
||||
}
|
||||
|
||||
// test, whether we reached the end of the underlying stream
|
||||
template <typename MultiPass>
|
||||
static bool input_at_eof(MultiPass const& mp, value_type const& t)
|
||||
{
|
||||
return t == mp.ftor.eof;
|
||||
}
|
||||
|
||||
typename Functor::first_type& get_functor() const
|
||||
{
|
||||
return ftor;
|
||||
}
|
||||
|
||||
mutable functor_type ftor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Functor>
|
||||
struct shared
|
||||
{
|
||||
explicit shared(Functor const& x) : ftor(x.second) {}
|
||||
|
||||
mutable typename Functor::second_type ftor;
|
||||
};
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, 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_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_SPLIT_DEQUE_POLICY_APR_06_2008_0138PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace spirit { namespace multi_pass_policies
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// class split_std_deque
|
||||
//
|
||||
// Implementation of the StoragePolicy used by multi_pass
|
||||
// This stores all data in a std::vector (despite its name), and keeps an
|
||||
// offset to the current position. It stores all the data unless there is
|
||||
// only one iterator using the queue.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
struct split_std_deque
|
||||
{
|
||||
enum { threshold = 16 };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
class unique //: public detail::default_storage_policy
|
||||
{
|
||||
private:
|
||||
typedef std::vector<Value> queue_type;
|
||||
|
||||
protected:
|
||||
unique()
|
||||
: queued_position(0)
|
||||
{}
|
||||
|
||||
unique(unique const& x)
|
||||
: queued_position(x.queued_position)
|
||||
{}
|
||||
|
||||
void swap(unique& x)
|
||||
{
|
||||
spirit::detail::swap(queued_position, x.queued_position);
|
||||
}
|
||||
|
||||
// This is called when the iterator is dereferenced. It's a
|
||||
// template method so we can recover the type of the multi_pass
|
||||
// iterator and call advance_input and input_is_valid.
|
||||
template <typename MultiPass>
|
||||
static typename MultiPass::reference
|
||||
dereference(MultiPass const& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
if (0 == mp.queued_position)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
queue.push_back(Value());
|
||||
return MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
return queue[mp.queued_position++];
|
||||
}
|
||||
else if (!MultiPass::input_is_valid(mp, queue[mp.queued_position-1]))
|
||||
{
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position-1]);
|
||||
}
|
||||
return queue[mp.queued_position-1];
|
||||
}
|
||||
|
||||
// This is called when the iterator is incremented. It's a template
|
||||
// method so we can recover the type of the multi_pass iterator
|
||||
// and call is_unique and advance_input.
|
||||
template <typename MultiPass>
|
||||
static void increment(MultiPass& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
typename queue_type::size_type size = queue.size();
|
||||
BOOST_ASSERT(0 != size && mp.queued_position <= size);
|
||||
if (mp.queued_position == size)
|
||||
{
|
||||
// check if this is the only iterator
|
||||
if (size >= threshold && MultiPass::is_unique(mp))
|
||||
{
|
||||
// free up the memory used by the queue. we avoid
|
||||
// clearing the queue on every increment, though,
|
||||
// because this would be too time consuming
|
||||
|
||||
// erase all but first item in queue
|
||||
queue.erase(queue.begin()+1, queue.end());
|
||||
mp.queued_position = 0;
|
||||
|
||||
// reuse first entry in the queue and initialize
|
||||
// it from the input
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new entry in the queue and initialize
|
||||
// it from the input
|
||||
queue.push_back(Value());
|
||||
MultiPass::advance_input(mp, queue[mp.queued_position++]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++mp.queued_position;
|
||||
}
|
||||
}
|
||||
|
||||
// called to forcibly clear the queue
|
||||
template <typename MultiPass>
|
||||
static void clear_queue(MultiPass& mp)
|
||||
{
|
||||
mp.shared->queued_elements.clear();
|
||||
mp.queued_position = 0;
|
||||
}
|
||||
|
||||
// called to determine whether the iterator is an eof iterator
|
||||
template <typename MultiPass>
|
||||
static bool is_eof(MultiPass const& mp)
|
||||
{
|
||||
queue_type& queue = mp.shared->queued_elements;
|
||||
return 0 != mp.queued_position &&
|
||||
mp.queued_position == queue.size() &&
|
||||
MultiPass::input_at_eof(mp, queue[mp.queued_position-1]);
|
||||
}
|
||||
|
||||
// called by operator==
|
||||
template <typename MultiPass>
|
||||
static bool equal_to(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queued_position == x.queued_position;
|
||||
}
|
||||
|
||||
// called by operator<
|
||||
template <typename MultiPass>
|
||||
static bool less_than(MultiPass const& mp, MultiPass const& x)
|
||||
{
|
||||
return mp.queued_position < x.queued_position;
|
||||
}
|
||||
|
||||
template <typename MultiPass>
|
||||
static void destroy(MultiPass&)
|
||||
{}
|
||||
|
||||
protected:
|
||||
mutable typename queue_type::size_type queued_position;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename Value>
|
||||
struct shared
|
||||
{
|
||||
shared() { queued_elements.reserve(threshold); }
|
||||
|
||||
typedef std::vector<Value> queue_type;
|
||||
queue_type queued_elements;
|
||||
};
|
||||
|
||||
}; // split_std_deque
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
// http://spirit.sourceforge.net/
|
||||
//
|
||||
// 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_LOOK_AHEAD_MAR_16_2007_1253PM)
|
||||
#define BOOST_SPIRIT_ITERATOR_LOOK_AHEAD_MAR_16_2007_1253PM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/detail/input_iterator_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/first_owner_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/fixed_size_queue_policy.hpp>
|
||||
#include <boost/spirit/home/support/iterators/multi_pass.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// this could be a template typedef, since such a thing doesn't
|
||||
// exist in C++, we'll use inheritance to accomplish the same thing.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, std::size_t N>
|
||||
class look_ahead :
|
||||
public multi_pass<
|
||||
T,
|
||||
multi_pass_policies::input_iterator,
|
||||
multi_pass_policies::first_owner,
|
||||
multi_pass_policies::no_check,
|
||||
multi_pass_policies::fixed_size_queue<N>
|
||||
>
|
||||
{
|
||||
private:
|
||||
typedef multi_pass<
|
||||
T,
|
||||
multi_pass_policies::input_iterator,
|
||||
multi_pass_policies::first_owner,
|
||||
multi_pass_policies::no_check,
|
||||
multi_pass_policies::fixed_size_queue<N> >
|
||||
base_type;
|
||||
|
||||
public:
|
||||
look_ahead()
|
||||
: base_type() {}
|
||||
|
||||
explicit look_ahead(T x)
|
||||
: base_type(x) {}
|
||||
|
||||
look_ahead(look_ahead const& x)
|
||||
: base_type(x) {}
|
||||
|
||||
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
look_ahead(int) // workaround for a bug in the library
|
||||
: base_type() {} // shipped with gcc 3.1
|
||||
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
|
||||
// default generated operators destructor and assignment operator are ok.
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2001, Daniel C. Nuffer
|
||||
// Copyright (c) 2001-2008, Hartmut Kaiser
|
||||
// http://spirit.sourceforge.net/
|
||||
//
|
||||
// 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_MULTI_PASS_MAR_16_2007_1124AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM
|
||||
|
||||
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
|
||||
#include <boost/spirit/home/support/iterators/detail/combine_policies.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace spirit
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The default multi_pass instantiation uses a ref-counted std_deque scheme.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template<typename T, typename Policies>
|
||||
class multi_pass
|
||||
: public Policies::BOOST_NESTED_TEMPLATE unique<T>
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
, typename iterator_base_creator<T, typename Policies::input_policy>::type
|
||||
#endif
|
||||
{
|
||||
private:
|
||||
// unique and shared data types
|
||||
typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T>
|
||||
policies_base_type;
|
||||
typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T>
|
||||
shared_data_type;
|
||||
|
||||
// define the types the standard embedded iterator typedefs are taken
|
||||
// from
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
typedef typename iterator_base_creator<Input, T>::type iterator_type;
|
||||
#else
|
||||
typedef typename policies_base_type::input_policy iterator_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// standard iterator typedefs
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename iterator_type::value_type value_type;
|
||||
typedef typename iterator_type::difference_type difference_type;
|
||||
typedef typename iterator_type::distance_type distance_type;
|
||||
typedef typename iterator_type::reference reference;
|
||||
typedef typename iterator_type::pointer pointer;
|
||||
|
||||
multi_pass()
|
||||
: shared(0)
|
||||
{}
|
||||
|
||||
explicit multi_pass(T input)
|
||||
: shared(new shared_data_type(input)), policies_base_type(input)
|
||||
{}
|
||||
|
||||
#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
// The standard library shipped with gcc-3.1 has a bug in
|
||||
// bits/basic_string.tcc. It tries to use iter::iter(0) to
|
||||
// construct an iterator. Ironically, this happens in sanity
|
||||
// checking code that isn't required by the standard.
|
||||
// The workaround is to provide an additional constructor that
|
||||
// ignores its int argument and behaves like the default constructor.
|
||||
multi_pass(int)
|
||||
: shared(0)
|
||||
{}
|
||||
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
|
||||
|
||||
~multi_pass()
|
||||
{
|
||||
if (policies_base_type::release(*this)) {
|
||||
policies_base_type::destroy(*this);
|
||||
delete shared;
|
||||
}
|
||||
}
|
||||
|
||||
multi_pass(multi_pass const& x)
|
||||
: shared(x.shared), policies_base_type(x)
|
||||
{
|
||||
policies_base_type::clone(*this);
|
||||
}
|
||||
|
||||
multi_pass& operator=(multi_pass const& x)
|
||||
{
|
||||
if (this != &x) {
|
||||
multi_pass temp(x);
|
||||
temp.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(multi_pass& x)
|
||||
{
|
||||
spirit::detail::swap(shared, x.shared);
|
||||
this->policies_base_type::swap(x);
|
||||
}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
policies_base_type::check(*this);
|
||||
return policies_base_type::dereference(*this);
|
||||
}
|
||||
pointer operator->() const
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
|
||||
multi_pass& operator++()
|
||||
{
|
||||
policies_base_type::check(*this);
|
||||
policies_base_type::increment(*this);
|
||||
return *this;
|
||||
}
|
||||
multi_pass operator++(int)
|
||||
{
|
||||
multi_pass tmp(*this);
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void clear_queue()
|
||||
{
|
||||
policies_base_type::clear_queue(*this);
|
||||
}
|
||||
|
||||
bool operator==(multi_pass const& y) const
|
||||
{
|
||||
if (is_eof())
|
||||
return y.is_eof();
|
||||
if (y.is_eof())
|
||||
return false;
|
||||
|
||||
return policies_base_type::equal_to(*this, y);
|
||||
}
|
||||
bool operator<(multi_pass const& y) const
|
||||
{
|
||||
return policies_base_type::less_than(*this, y);
|
||||
}
|
||||
|
||||
private: // helper functions
|
||||
bool is_eof() const
|
||||
{
|
||||
return (0 == shared) || policies_base_type::is_eof(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
shared_data_type *shared;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator!=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator>(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return y < x;
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator>=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(x < y);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline bool
|
||||
operator<=(multi_pass<T, Policies> const& x, multi_pass<T, Policies> const& y)
|
||||
{
|
||||
return !(y < x);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Generator function
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Policies, typename T>
|
||||
inline multi_pass<T, Policies>
|
||||
make_multi_pass(T i)
|
||||
{
|
||||
return multi_pass<T, Policies>(i);
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
inline void
|
||||
swap(multi_pass<T, Policies> &x,
|
||||
multi_pass<T, Policies> &y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
}} // namespace boost::spirit
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2007 Tobias Schwinger
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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_MULTI_PASS_FWD_APR_18_2008_1102AM)
|
||||
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_FWD_APR_18_2008_1102AM
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost { namespace spirit {
|
||||
|
||||
namespace multi_pass_policies
|
||||
{
|
||||
// input policies
|
||||
struct input_iterator;
|
||||
struct lex_input;
|
||||
struct functor_input;
|
||||
struct split_functor_input;
|
||||
|
||||
// ownership policies
|
||||
struct ref_counted;
|
||||
struct first_owner;
|
||||
|
||||
// checking policies
|
||||
class illegal_backtracking;
|
||||
struct buf_id_check;
|
||||
struct no_check;
|
||||
|
||||
// storage policies
|
||||
struct std_deque;
|
||||
template<std::size_t N> struct fixed_size_queue;
|
||||
}
|
||||
|
||||
template <typename T, typename Policies>
|
||||
class multi_pass;
|
||||
|
||||
template <typename T, typename Policies>
|
||||
void swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T> void swap(T& t1, T& t2);
|
||||
}
|
||||
|
||||
}} // namespace boost::spirit
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user