// 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 #include 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 ::value , bool CheckingIsEmpty = boost::is_empty::value , bool InputIsEmpty = boost::is_empty::value> struct multi_pass_unique; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Ownership, Checking, Input, Storage { multi_pass_unique() {} multi_pass_unique(T& x) : Input(x) {} multi_pass_unique(T const& x) : Input(x) {} template 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 inline static void clear_queue(MultiPass& mp) { Checking::clear_queue(mp); Storage::clear_queue(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Ownership, Checking, Storage { multi_pass_unique() {} multi_pass_unique(T const&) {} template 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 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 inline static void advance_input(MultiPass& mp) { Input::advance_input(mp); } template inline static typename MultiPass::reference get_input(MultiPass& mp) { return Input::get_input(mp); } template inline static bool input_at_eof(MultiPass const& mp) { return Input::input_at_eof(mp); } template inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) { return Input::input_is_valid(mp, curtok); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Ownership, Input, Storage { multi_pass_unique() {} multi_pass_unique(T& x) : Input(x) {} multi_pass_unique(T const& x) : Input(x) {} template 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 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 inline static void docheck(MultiPass const& mp) { Checking::docheck(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Ownership, Storage { multi_pass_unique() {} multi_pass_unique(T const&) {} template 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 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 inline static void advance_input(MultiPass& mp) { Input::advance_input(mp); } template inline static typename MultiPass::reference get_input(MultiPass& mp) { return Input::get_input(mp); } template inline static bool input_at_eof(MultiPass const& mp) { return Input::input_at_eof(mp); } template 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 inline static void docheck(MultiPass const& mp) { Checking::docheck(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Checking, Input, Storage { multi_pass_unique() {} multi_pass_unique(T& x) : Input(x) {} multi_pass_unique(T const& x) : Input(x) {} template 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 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 inline static void clone(MultiPass& mp) { Ownership::clone(mp); } template inline static bool release(MultiPass& mp) { return Ownership::release(mp); } template inline static bool is_unique(MultiPass const& mp) { return Ownership::is_unique(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Checking, Storage { multi_pass_unique() {} multi_pass_unique(T const&) {} template 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 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 inline static void advance_input(MultiPass& mp) { Input::advance_input(mp); } template inline static typename MultiPass::reference get_input(MultiPass& mp) { return Input::get_input(mp); } template inline static bool input_at_eof(MultiPass const& mp) { return Input::input_at_eof(mp); } template 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 inline static void clone(MultiPass& mp) { Ownership::clone(mp); } template inline static bool release(MultiPass& mp) { return Ownership::release(mp); } template inline static bool is_unique(MultiPass const& mp) { return Ownership::is_unique(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Input, Storage { multi_pass_unique() {} multi_pass_unique(T& x) : Input(x) {} multi_pass_unique(T const& x) : Input(x) {} template 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 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 inline static void docheck(MultiPass const& mp) { Checking::docheck(mp); } // ownership policy functions are forwarded to the Ownership type template inline static void clone(MultiPass& mp) { Ownership::clone(mp); } template inline static bool release(MultiPass& mp) { return Ownership::release(mp); } template inline static bool is_unique(MultiPass const& mp) { return Ownership::is_unique(mp); } }; /////////////////////////////////////////////////////////////////////////// template struct multi_pass_unique : Storage { multi_pass_unique() {} multi_pass_unique(T const&) {} template static void destroy(MultiPass& mp) { Input::destroy(mp); Storage::destroy(mp); } void swap(multi_pass_unique& x) { this->Storage::swap(x); } template 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 inline static void advance_input(MultiPass& mp) { Input::advance_input(mp); } template inline static typename MultiPass::reference get_input(MultiPass& mp) { return Input::get_input(mp); } template inline static bool input_at_eof(MultiPass const& mp) { return Input::input_at_eof(mp); } template 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 inline static void docheck(MultiPass const& mp) { Checking::docheck(mp); } // ownership policy functions are forwarded to the Ownership type template inline static void clone(MultiPass& mp) { Ownership::clone(mp); } template inline static bool release(MultiPass& mp) { return Ownership::release(mp); } template 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 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 struct default_policy { typedef Ownership ownership_policy; typedef Checking checking_policy; typedef Input input_policy; typedef Storage storage_policy; /////////////////////////////////////////////////////////////////////// template struct unique : multi_pass_unique , typename Storage::BOOST_NESTED_TEMPLATE unique< typename Input::BOOST_NESTED_TEMPLATE unique::value_type> > { typedef typename Ownership::unique ownership_policy; typedef typename Checking::unique checking_policy; typedef typename Input::BOOST_NESTED_TEMPLATE unique input_policy; typedef typename Storage::BOOST_NESTED_TEMPLATE unique< typename input_policy::value_type> storage_policy; typedef multi_pass_unique unique_base_type; unique() {} explicit unique(T& input) : unique_base_type(input) {} explicit unique(T const& input) : unique_base_type(input) {} }; /////////////////////////////////////////////////////////////////////// template struct shared : multi_pass_shared , typename Storage::BOOST_NESTED_TEMPLATE shared< typename Input::BOOST_NESTED_TEMPLATE unique::value_type> > { typedef typename Ownership::shared ownership_policy; typedef typename Checking::shared checking_policy; typedef typename Input::BOOST_NESTED_TEMPLATE shared input_policy; typedef typename Storage::BOOST_NESTED_TEMPLATE shared< typename Input::BOOST_NESTED_TEMPLATE unique::value_type> storage_policy; typedef multi_pass_shared 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